/* ============================================================================
   brand.css · the committed look and feel for the Supercomputing Challenge
   curriculum pages.  Import it from every page:

       <link rel="stylesheet" href="brand.css">

   Consumers: apps/supercomputingchallenge/{index, laser, sti, simtable}
   Author:    Debbie (senior-uxui-designer · bead c4a8e2f1) for Stephen Guerin
   Feeds:     r4-scc-look-and-feel.html  — this is r4's palette taken DARK.

   WHAT THIS IS.  A token set + base rules.  Dark mode, large type, the
   Challenge's blues and grays made sharper than a .org template, with one
   restrained New-Mexico note.  Pages add their own layout; they should not
   re-declare color or type.

   ── THE THREE RULES YOU MAY NOT BREAK ──────────────────────────────────────
   1. THE FONT FLOOR IS 15px. Nothing on any page renders below --fs-xs.
      This is not taste. Stephen is 58 and uses readers, and these pages run
      on a projector at the back of a classroom. Body is 18px. Controls and
      labels are 16px. Small print bottoms out at 15px and goes no lower.
      If something "doesn't fit", cut the words — do not shrink the type.
   2. --laser IS THE DOT. It is the one red on the page and it is never
      decorative. If it isn't the laser, the live signal, or a real error,
      it isn't --laser.
   3. CONTRAST IS CHECKED, NOT ASSUMED. Every text token below carries its
      measured ratio against --canvas. All body-sized text is >= WCAG AA
      (4.5:1); most clears AAA. Don't add a token without measuring it.
   ========================================================================== */

:root{
  /* ── CANVAS & SURFACES ──────────────────────────────────────────────────
     Layered, not flat. Depth comes from these three plus --border — never
     from a drop shadow doing the work alone. Dark rooms, bright projectors. */
  --canvas:      #080d14;   /* page background. near-black, blue-shifted (not gray) */
  --surface:     #0f1826;   /* panels, cards, the default raised plane */
  --raised:      #17232f;   /* a card on a card: popovers, active rows, code wells */
  --sunken:      #050a10;   /* wells the eye should fall INTO: video, logs, terminals */
  --header:      linear-gradient(#0d1b2a,#15304d);  /* hero / masthead only */

  /* ── TEXT ───────────────────────────────────────────────────────────────
     Ratios measured against --canvas #080d14. */
  --text:        #eef4fb;   /* 17.4:1 · body and headings. AAA. */
  --muted:       #a8bdd2;   /* 9.8:1  · secondary prose, captions. AAA at body size. */
  --faint:       #7f97b0;   /* 5.9:1  · metadata, timestamps, tree scaffolding. AA. */
                            /*          --faint is the FLOOR of legibility: never
                                        put it below 15px and never on --raised. */
  --on-brand:    #ffffff;   /* text sitting on a --blue or --laser fill */

  /* ── BRAND ──────────────────────────────────────────────────────────────
     The Challenge is blues + grays, science-forward, encouraging. On dark,
     their #1b4f8f can only be a FILL — it has no contrast as text. So the
     blue splits in two: a deep structural blue and a lifted readable sky. */
  --blue:        #1b4f8f;   /* THE Challenge blue. Fills, buttons, rails. Not text. */
  --blue-lift:   #2e7fd4;   /* button hover, active rail, chart strokes */
  --sky:         #4f9ae8;   /* 6.5:1  · links, active tab, anything blue that is TEXT */
  --sky-wash:    #12263c;   /* a tint of blue for selected rows / quiet emphasis */

  /* ── ACCENTS · earned, not decorative ───────────────────────────────────
     The New-Mexico note is TURQUOISE. It is the regional pride token — the
     one that says Land of Enchantment without a hot-air balloon. Use it for
     the substrate: the namespace, beads, provenance, "this is ours".
     --chile is the warm counterweight: attention, gates, a human must look.
     Between them they cover everything --laser must not be spent on. */
  --nm:          #35d0c0;   /* 9.9:1  · turquoise. the acequia / the namespace / identity */
  --nm-wash:     #0c2b2b;   /* its surface tint */
  --chile:       #f5b04b;   /* 10.2:1 · desert/chile warm. gates, warnings, "pending" */
  --chile-wash:  #2a1f0c;
  --laser:       #ff5347;   /* 6.0:1  · THE DOT. see rule 2. also: real errors. */
  --live:        #58d68a;   /* 10.4:1 · success, connected, verified, "you can write here" */
  --live-wash:   #0c2417;

  /* ── LINES ──────────────────────────────────────────────────────────────*/
  --border:      #24374d;   /* the default hairline. visible on canvas AND on surface. */
  --border-soft: #182838;   /* dividers inside a card, where a full line is too loud */

  /* ── THE MARKER · the human hand ────────────────────────────────────────
     Handwriting on a printout. This is the annotation voice — a designer
     talking over the artifact. It is NEVER product UI: if a user has to read
     it to operate the page, it's the wrong token. 15px floor applies here too
     (cursive faces read small — this is why --fs-xs is its minimum). */
  --marker:      #ffd24a;
  --marker-ink:  #4a3c00;   /* marker text on a light marker fill */
  --font-marker: 'Segoe Print','Comic Sans MS',cursive;

  /* ── TYPE ───────────────────────────────────────────────────────────────*/
  --font:        "Segoe UI",system-ui,-apple-system,Roboto,Helvetica,Arial,sans-serif;
  --font-mono:   ui-monospace,Consolas,Menlo,"Courier New",monospace;

  /* The scale. ~1.25 ratio, anchored at 18px body. Read the floor comment. */
  --fs-xs:   15px;  /* ⛔ THE FLOOR. small print, legends, marker. NOTHING SMALLER. */
  --fs-sm:   16px;  /* controls, labels, buttons, tabs, chips, table cells */
  --fs-md:   18px;  /* BODY. the default. */
  --fs-lg:   21px;  /* lede paragraphs, card titles */
  --fs-xl:   26px;  /* h3 */
  --fs-2xl:  33px;  /* h2 */
  --fs-3xl:  42px;  /* h1 */
  --fs-4xl:  54px;  /* hero only, one per page */

  --lh-tight: 1.15; /* headings */
  --lh-body:  1.6;  /* prose. generous on purpose — projector + readers. */

  /* ── SPACE ──────────────────────────────────────────────────────────────*/
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  /* ── RADII ──────────────────────────────────────────────────────────────*/
  --r-sm: 6px; --r-md: 10px; --r-lg: 14px; --r-pill: 999px;

  /* ── FOCUS ──────────────────────────────────────────────────────────────
     Gold, because it is the only hue that survives on top of --canvas,
     --surface, --blue AND --laser. Keyboard users are not an edge case in a
     classroom. Do not set outline:none anywhere without replacing this. */
  --focus:       #ffd24a;
  --focus-ring:  3px solid var(--focus);
  --focus-off:   2px;

  --shadow: 0 10px 30px rgba(0,0,0,.45);
  --ease:   cubic-bezier(.2,.85,.25,1);
}

/* ============================================================================
   LIGHT THEME · ADDITIVE AND OPT-IN.  DARK ABOVE IS STILL THE DEFAULT.
   Added 2026-07-15 for the laser lab's theme switch. Nothing above this line
   changed — every existing page keeps rendering exactly as it did.

   HOW TO TURN IT ON:  <html data-theme="light">   (JS sets the attribute)
   Set nothing and you get dark, as before. `[data-theme="light"]` also works
   on a subtree if a page ever needs one light island inside a dark page.

   ── THE MIRROR CONSTRAINT · READ THIS BEFORE YOU TOUCH A VALUE ─────────────
   The dark block above says: the Challenge's #1b4f8f "can only be a FILL — it
   has no contrast as text", which is WHY the blue splits into --blue (fill)
   and --sky (the lifted, readable blue-as-text). Measured: #1b4f8f as text on
   --canvas #080d14 is 2.38:1 — a hard FAIL. That is a real constraint, not a
   preference.

   ON LIGHT, THAT CONSTRAINT INVERTS — and this is the whole design of this
   block. Measured against light --canvas #e8eef6:
     · --blue #1b4f8f as TEXT  = 7.02:1  AAA.  On light the Challenge blue is
       finally readable as text. The split still exists, but --blue is no
       longer barred from text — it is the honest brand blue, unlifted.
     · --sky  #4f9ae8 as TEXT  = 2.53:1  FAIL. The token that RESCUED the blue
       on dark is the one that BREAKS on light. So --sky must DARKEN here,
       exactly as far as it was lifted there. Same hue (211deg, unchanged),
       opposite direction.
   Generalised: on dark, brand colours must be LIFTED to be text; on light they
   must be DEEPENED. Every accent below is its dark twin deepened, hue held to
   within 2deg (measured) so --nm still reads turquoise and --laser still reads
   as the dot. If you add a token, deepen — do not pick a new colour.

   Contrast is measured, not assumed (rule 3). Ratios below are vs light
   --canvas #e8eef6, and EVERY text token also clears AA (4.5:1) on --surface,
   --raised AND --sunken — the worst case is --sunken, which on light is the
   plane where accents get closest to the floor (on dark the danger plane is
   --raised; that also mirrors).
   ========================================================================== */
:root[data-theme="light"],
[data-theme="light"]{
  color-scheme: light;   /* native controls, scrollbars and form UI follow */

  /* ── CANVAS & SURFACES ──────────────────────────────────────────────────
     Same depth ladder as dark, same direction: higher plane = lighter.
     sunken < canvas < surface < raised. Still blue-shifted, never neutral
     gray — the page should read as the Challenge's blue, lit. */
  --canvas:      #e8eef6;   /* page background. light, blue-shifted (not white) */
  --surface:     #f6f9fc;   /* panels, cards, the default raised plane */
  --raised:      #ffffff;   /* a card on a card: popovers, active rows, code wells */
  --sunken:      #d8e2ee;   /* wells the eye should fall INTO: inputs, logs, code */
  --header:      linear-gradient(#dce9f8,#c3daf2);  /* hero. NOTE: on light the hero
                              must stay LIGHT — --text is dark now, so the deep
                              #0d1b2a..#15304d gradient of dark mode would swallow
                              it. --text on #c3daf2 = 12.3:1. */

  /* ── TEXT ─────────────────────────────────────────────────────────────── */
  --text:        #0d1a26;   /* 15.1:1 · body and headings. AAA. */
  --muted:       #3c4e63;   /*  7.3:1 · secondary prose, captions. AAA at body size. */
  --faint:       #4e6173;   /*  5.5:1 · metadata, timestamps, scaffolding. AA.
                                        Still the FLOOR of legibility: never below
                                        15px. On light its worst plane is --sunken
                                        (4.9:1), not --raised — the mirror of dark. */
  --on-brand:    #ffffff;   /* text on a --blue or --laser fill. white on --blue
                               = 8.2:1; white on light --laser = 6.1:1. */

  /* ── BRAND ──────────────────────────────────────────────────────────────
     See THE MIRROR CONSTRAINT above. --blue is UNCHANGED from dark: it is the
     Challenge's own #1b4f8f, and on light it is both the fill AND legal as text. */
  --blue:        #1b4f8f;   /*  7.0:1 · THE Challenge blue. Fills, buttons, rails —
                                        and on light, unlike dark, it may be TEXT. */
  --blue-lift:   #17406f;   /* button hover, active rail, chart strokes. On light,
                                        "lift" means DEEPEN: the hover has to move AWAY
                                        from the canvas, not toward it. Keeping dark's
                                        #2e7fd4 here would put white-on-hover at 4.1:1
                                        (fails AA at our 16px/600 buttons); this is
                                        10.5:1. Same mirror rule as --sky. */
  --sky:         #135aa6;   /*  5.9:1 · links, active tab, blue-as-text. The dark
                                        --sky #4f9ae8 deepened; hue 211deg held. */
  --sky-wash:    #dbe8f9;   /* tint for selected rows / quiet emphasis */

  /* ── ACCENTS · earned, not decorative ───────────────────────────────────
     Each is its dark twin deepened. Hue drift measured, all <= 2deg, so the
     New-Mexico turquoise still says New Mexico and --laser still says laser. */
  --nm:          #086b61;   /*  5.5:1 · turquoise (hue 174deg, same as #35d0c0) */
  --nm-wash:     #d6f2ee;
  --chile:       #855706;   /*  5.3:1 · desert/chile warm (hue 38deg vs 36deg) */
  --chile-wash:  #fcefd8;
  --laser:       #bd2619;   /*  5.2:1 · THE DOT. Rule 2 still binds — this is the
                                        one red, never decorative. (hue 5deg vs 4deg) */
  --live:        #116a37;   /*  5.7:1 · success, connected, verified */
  --live-wash:   #dcf5e5;

  /* ── LINES ──────────────────────────────────────────────────────────────
     Parity with dark: dark --border is 1.60:1 on its canvas, so light --border
     is tuned to 1.52:1 on its own — the same weight of hairline, not heavier. */
  --border:      #b3c4d9;   /* visible on canvas AND on surface */
  --border-soft: #dde5ef;   /* dividers inside a card */

  /* ── THE MARKER · the human hand ────────────────────────────────────────
     #ffd24a is 1.23:1 on light — the marker would be an invisible ghost. It
     deepens to a dark amber (hue 47deg vs 45deg): still handwriting, still the
     annotation voice, now actually readable. --marker-ink is unchanged; it was
     always "marker text on a LIGHT marker fill", which is this case. */
  --marker:      #765c00;   /*  5.5:1 */
  --marker-ink:  #4a3c00;

  /* ── FOCUS ──────────────────────────────────────────────────────────────
     Dark picked gold because it survives on canvas/surface/blue/laser. On light,
     gold is 1.23:1 — gone. Because the ring is drawn with outline-offset (it
     sits on the PAGE background, never on the button fill), it only has to beat
     canvas/surface/raised: 4.4 / 4.9 / 5.2 — all past the 3:1 non-text bar.
     Same amber family as dark's gold, deepened. */
  --focus:       #a85800;
  --focus-ring:  3px solid var(--focus);

  /* Light rooms don't need a 45% black bloom; that reads as dirt on white. */
  --shadow: 0 10px 30px rgba(13,26,38,.14);
}

/* The handful of base rules that hard-code a colour rather than a token need a
   light twin. These are ADDITIONS — the dark rules they mirror are untouched. */
[data-theme="light"] a{border-bottom-color:rgba(19,90,166,.35)}   /* --sky deepened, .35 alpha */
[data-theme="light"] .marker-note{background:rgba(118,92,0,.07)}  /* --marker deepened */

/* ============================ BASE ======================================= */
*{box-sizing:border-box}

body{
  margin:0;
  background:var(--canvas);
  color:var(--text);
  font:var(--fs-md)/var(--lh-body) var(--font);
  -webkit-font-smoothing:antialiased;
}

/* Headings: genuinely large, tight, and NOT pure white at the top end —
   --text at 42px is already loud enough. Letter-spacing tightens as size
   grows; that's the whole trick that makes this not look like a template. */
h1,h2,h3,h4{margin:0 0 var(--s3);line-height:var(--lh-tight);font-weight:700}
h1{font-size:var(--fs-3xl);letter-spacing:-1px}
h2{font-size:var(--fs-2xl);letter-spacing:-.6px}
h3{font-size:var(--fs-xl);letter-spacing:-.3px}
h4{font-size:var(--fs-lg);letter-spacing:-.1px}
p{margin:0 0 var(--s4);max-width:70ch}   /* measure cap: prose stops being prose past ~70ch */

/* The eyebrow + the section label. The only two places uppercase is allowed
   (uppercase costs legibility — spend it only on 2-4 word labels). */
.eyebrow{color:var(--chile);font-size:var(--fs-sm);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;margin:0 0 var(--s3)}
.h2-label{color:var(--muted);font-size:var(--fs-sm);font-weight:700;
  letter-spacing:.09em;text-transform:uppercase;margin:var(--s7) 0 var(--s1)}
.lede{font-size:var(--fs-lg);color:var(--muted);max-width:66ch;margin:0 0 var(--s5)}
small,.small{font-size:var(--fs-xs)}  /* and no further. */

a{color:var(--sky);text-decoration:none;border-bottom:1px solid rgba(79,154,232,.35)}
a:hover{color:var(--nm);border-bottom-color:var(--nm)}

/* Focus: one rule, everything, no exceptions. */
:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-off);border-radius:var(--r-sm)}

/* ============================ CONTROLS ================================== */
/* 16px minimum on anything you click or type into. A 13px button is a button
   for someone else. Hit targets ~40px tall so a projector-lit room can find
   them and a shaky hand can hit them. */
button,.btn{
  font:600 var(--fs-sm)/1 var(--font);
  background:var(--blue);color:var(--on-brand);
  border:1px solid transparent;border-radius:var(--r-md);
  padding:var(--s3) var(--s4);min-height:40px;cursor:pointer;
  transition:background .15s var(--ease),transform .1s var(--ease);
}
button:hover,.btn:hover{background:var(--blue-lift)}
button:active{transform:translateY(1px)}
button:disabled{opacity:.4;cursor:not-allowed;transform:none}
button.ghost{background:transparent;color:var(--text);border-color:var(--border)}
button.ghost:hover{background:var(--raised);border-color:var(--sky)}
button.nm{background:transparent;color:var(--nm);border-color:var(--nm)}
button.nm:hover{background:var(--nm-wash)}

input,textarea,select{
  font:var(--fs-sm)/1.5 var(--font);
  background:var(--sunken);color:var(--text);
  border:1px solid var(--border);border-radius:var(--r-md);
  padding:var(--s3) var(--s4);
}
input::placeholder,textarea::placeholder{color:var(--faint)}
input:focus,textarea:focus{border-color:var(--sky)}
label{font-size:var(--fs-sm);color:var(--muted);display:inline-block;margin-bottom:var(--s1)}

code,.mono{font:var(--fs-xs)/1.5 var(--font-mono);
  background:var(--raised);border:1px solid var(--border-soft);
  border-radius:var(--r-sm);padding:1px 6px;color:var(--nm)}

/* ============================ SURFACES ================================== */
.card{
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r-lg);padding:var(--s5);
}
.card.raised{background:var(--raised);box-shadow:var(--shadow)}

/* A card that is also a button. Top rail = its state, and the rail is the
   only place --sky/--live/--chile compete for the eye. */
.card.pick{cursor:pointer;border-top:3px solid var(--sky);
  transition:transform .15s var(--ease),border-color .15s var(--ease)}
.card.pick:hover{transform:translateY(-3px);border-color:var(--sky)}

.pill{display:inline-flex;align-items:center;gap:var(--s2);
  background:var(--raised);border:1px solid var(--border);
  border-radius:var(--r-pill);padding:var(--s2) var(--s3);
  font-size:var(--fs-xs);color:var(--muted)}
.pill.live{border-color:var(--live);color:var(--live);background:var(--live-wash)}
.pill.nm{border-color:var(--nm);color:var(--nm);background:var(--nm-wash)}
.pill.pending{border-color:var(--chile);color:var(--chile);background:var(--chile-wash)}

/* ============================ TABS ====================================== */
/* The rail under the active tab is --laser: the tab bar is the one piece of
   chrome the dot is allowed to touch, because it's what the page is about.
   Pages should ANIMATE .tab-rail's transform between tabs, never hard-cut. */
.tabs{display:flex;gap:var(--s1);border-bottom:2px solid var(--border);
  position:relative;flex-wrap:wrap}
.tab{background:none;border:0;border-radius:0;color:var(--muted);
  font:600 var(--fs-sm)/1 var(--font);padding:var(--s4) var(--s5);min-height:48px}
.tab:hover{background:var(--surface);color:var(--text)}
.tab[aria-selected="true"]{color:var(--sky)}
.tab-rail{position:absolute;bottom:-2px;height:3px;background:var(--laser);
  border-radius:2px;transition:transform .42s var(--ease),width .42s var(--ease)}

/* ============================ THE MARKER ================================ */
.marker{font:var(--fs-xs)/1.55 var(--font-marker);color:var(--marker)}
.marker-note{border:2px dashed var(--marker);border-radius:var(--r-md);
  background:rgba(255,210,74,.06);padding:var(--s4) var(--s5);
  font:var(--fs-md)/var(--lh-body) var(--font-marker);color:var(--marker)}

/* ============================ MOTION ==================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}

/* ── COMMITTED PALETTE, for the record ──────────────────────────────────────
   canvas #080d14 · surface #0f1826 · raised #17232f · sunken #050a10
   text   #eef4fb · muted   #a8bdd2 · faint  #7f97b0
   blue   #1b4f8f · blue-lift #2e7fd4 · sky  #4f9ae8
   nm     #35d0c0 · chile   #f5b04b · laser #ff5347 · live #58d68a
   border #24374d · marker  #ffd24a · focus #ffd24a
   ──────────────────────────────────────────────────────────────────────────
   v0.1.0 · 2026-07-14 · © 2026 RedfishGroup · author: Debbie for Stephen Guerin
   all rights reserved (unless otherwise specified) */
