/* ════════════════════════════════════════════════════════════════════
   TSSA — READING PERSONAS

   Five ways to read the same site: Wild (teens), Street (youth), House
   (adults, the default), Boardroom (executives), Comfort (older folk).

   Rudy: "besides the themes the text shift as well for an advanced unique
   experience." Typography is what does the transforming — a palette repaints
   a page, a typeface rebuilds it.

   ══ THE ONE RULE ══

   A PERSONA NEVER WRITES A BRAND COLOUR. Two systems already own colour on
   <html>: the time-of-day palette the anthem player sets via data-theme, and
   the SA sport themes a visitor picks as inline custom properties, which are
   documented to win. A third writer of --gold or --bg would fight both.

   So these blocks set faces, scale, rhythm and corners only. The single
   exception is Comfort raising --t1/--t2, which is legibility rather than
   decoration and leaves --gold and --bg alone.

   Loaded by BOTH layers — app/layout.tsx and public/index-public.html — like
   tssa-theme.css, so the static page and the React routes can never drift.
   ════════════════════════════════════════════════════════════════════ */

:root {
  /* Defaults, so anything consuming these works with no persona set at all. */
  --p-scale:      1;       /* multiplies the base reading size            */
  --p-lh:         1.65;    /* body line-height                            */
  --p-head-lh:    1.06;    /* heading line-height                         */
  --p-head-ls:    -0.01em; /* heading letter-spacing                      */
  --p-head-wt:    400;     /* heading weight                              */
  --p-body-wt:    300;     /* body weight                                 */
  --p-radius:     12px;    /* the corner the whole site rounds to         */
  --p-pill:       999px;   /* buttons                                     */
  --p-eyebrow-ls: .2em;    /* the uppercase micro-labels                  */
  --p-accent:     var(--gold);
}

/* ── WILD · teens ──────────────────────────────────────────────────────
   Heavy, tight, round. Bricolage Grotesque is an optical-size variable face
   that gets more characterful as it grows, which is exactly right for a page
   whose headline is the loudest thing on it. */
:root[data-persona="wild"] {
  --serif: 'Bricolage Grotesque', 'Playfair Display', Georgia, serif;
  --sans:  'Nunito', 'Inter', system-ui, sans-serif;
  --p-scale:      1.04;
  --p-lh:         1.6;
  --p-head-lh:    0.94;
  --p-head-ls:    -0.035em;
  --p-head-wt:    800;
  --p-body-wt:    400;
  --p-radius:     20px;
  --p-eyebrow-ls: .16em;
  --p-accent:     #FF6B4A;
}

/* ── STREET · youth ────────────────────────────────────────────────────
   The way a well-made app feels: geometric display, neutral body, confident
   spacing. Nothing shouts, nothing whispers. */
:root[data-persona="street"] {
  --serif: 'Sora', 'Playfair Display', Georgia, serif;
  --sans:  'DM Sans', 'Inter', system-ui, sans-serif;
  --p-scale:      1.02;
  --p-lh:         1.62;
  --p-head-lh:    1.02;
  --p-head-ls:    -0.028em;
  --p-head-wt:    700;
  --p-body-wt:    400;
  --p-radius:     14px;
  --p-eyebrow-ls: .18em;
  --p-accent:     #3DD9A4;
}

/* ── HOUSE · adults — THE DEFAULT ──────────────────────────────────────
   Identical to the site as it has always been -- delivered by writing NOTHING,
   which is the only way to be certain of it. The two faces it names are
   already in the page for every visitor, so it also loads nothing. */
:root[data-persona="house"] {
  /* DELIBERATELY NO --serif, NO --sans AND NO --p-* SHAPE TOKENS.

     This block used to set all of them, and it was wrong in a way only a
     browser could show. Measured on production 8 Sep 2026, the same page with
     the attribute on and then off:

       body    16px / 400          ->  15px / 300
       h1      Cormorant Garamond  ->  Playfair Display
       h2      Cormorant Garamond  ->  Playfair Display, leading 33px -> 23px
       p       400                 ->  300
       button  400                 ->  300

     House is not a persona that resembles the site; House IS the site. The
     switcher writes data-persona="house" for a first-time visitor so the panel
     can show which one is active, so the attribute reaches nearly every page
     on the platform — which turned every row above into a site-wide typography
     change shipped by accident.

     The only correct House rule is no rule. Every application rule below is
     scoped :not([data-persona="house"]) for the same reason. The accent stays,
     because House still needs a colour for its own switcher dot, and nothing
     outside .pers-* reads --p-accent. */
  --p-accent: var(--gold);
}

/* ── BOARDROOM · executives ────────────────────────────────────────────
   Tighter, squarer, faster to scan. Someone reading this between meetings
   wants the figure and the date, not the atmosphere. */
:root[data-persona="boardroom"] {
  --serif: 'Newsreader', Georgia, serif;
  --sans:  'IBM Plex Sans', 'Inter', system-ui, sans-serif;
  --p-scale:      0.98;
  --p-lh:         1.55;
  --p-head-lh:    1.1;
  --p-head-ls:    -0.005em;
  --p-head-wt:    500;
  --p-body-wt:    400;
  --p-radius:     6px;
  --p-pill:       6px;
  --p-eyebrow-ls: .22em;
  --p-accent:     #8FA6C4;
}

/* ── COMFORT · older folk ──────────────────────────────────────────────
   NOT A NOVELTY SETTING. Atkinson Hyperlegible was drawn by the Braille
   Institute so that people with low vision can tell characters apart — its
   'l', '1' and 'I' are deliberately unlike one another.

   Everything here follows from that: an 18px base rather than 15, generous
   leading, NO weight below 400 anywhere, almost no letter-spacing (tracking
   hurts legibility at size), and text lifted toward white.

   The contrast lift is the one place a persona touches colour, and it moves
   only the two text tokens — --gold and --bg are left to the systems that
   own them. */
:root[data-persona="comfort"] {
  --serif: 'Bitter', Georgia, serif;
  --sans:  'Atkinson Hyperlegible', 'Inter', system-ui, sans-serif;
  --p-scale:      1.2;
  --p-lh:         1.85;
  --p-head-lh:    1.2;
  --p-head-ls:    0;
  --p-head-wt:    700;
  --p-body-wt:    400;
  --p-radius:     10px;
  --p-eyebrow-ls: .1em;
  --p-accent:     #E8D08A;
  --t1: #FFFDF8;
  --t2: #F0EADC;
  --t3: #D8D0BE;
}

/* ── APPLYING IT ───────────────────────────────────────────────────────
   Scoped AWAY FROM HOUSE, which must leave the site exactly as it is.

   THE BASE IS 16px BECAUSE THAT IS WHAT THE SITE'S BODY ACTUALLY COMPUTES TO.
   The first cut used 15px, which meant Wild — the loud one — shipped at
   15.6px against the site's own 16px and read SMALLER than the page it was
   supposed to shout over. Measured, not assumed. */
:root[data-persona]:not([data-persona="house"]) body {
  font-family: var(--sans);
  font-size: calc(16px * var(--p-scale));
  font-weight: var(--p-body-wt);
  line-height: var(--p-lh);
}

/* h1 carries the persona's display leading, which is deliberately tight.
   h2 and h3 DO NOT: the site sets h2 at 1.5, and handing it Wild's 0.94 puts
   22px lines on top of one another the moment a heading wraps to two. They
   take the same face, weight and tracking, with the leading loosened.

   MEASURED: in practice most h1 on this site carry line-height INLINE
   (style="font-family:var(--serif);font-size:40px;line-height:1.05"), so the
   --p-head-lh below reaches h1 only where a component left it alone, and it
   is h2/h3 that show the persona's rhythm. That is left as it is on purpose.
   The inline 1.05 is already tight, and forcing 0.94 onto a hero headline
   with !important is how you get a two-line hero overlapping itself. The
   FACE and the WEIGHT are what carry a persona on an h1, and both do reach it
   -- the face because the inline style says var(--serif), the weight because
   the !important rule further down had to be added for exactly this reason. */
:root[data-persona]:not([data-persona="house"]) h1,
:root[data-persona]:not([data-persona="house"]) .hero h1,
:root[data-persona]:not([data-persona="house"]) .bk-title {
  font-family: var(--serif);
  font-weight: var(--p-head-wt);
  line-height: var(--p-head-lh);
  letter-spacing: var(--p-head-ls);
}
:root[data-persona]:not([data-persona="house"]) :is(h2, h3) {
  font-family: var(--serif);
  font-weight: var(--p-head-wt);
  line-height: calc(var(--p-head-lh) + 0.25);
  letter-spacing: var(--p-head-ls);
}

/* THE CORNER THE WHOLE PLATFORM ROUNDS TO. --radius and --radius-lg live in
   tssa-theme.css and are consumed by .btn, .card, .metric-card, .input, the
   profile band, the landmark tiles and a dozen more — so moving them is what
   makes this a LOOK rather than a font swap. Boardroom squares off to 6px,
   Wild rounds to 20px. --p-radius was declared for this from the start and
   was, until now, read by nothing. */
:root[data-persona]:not([data-persona="house"]) {
  --radius:    calc(var(--p-radius) * 0.667);
  --radius-lg: var(--p-radius);
}

/* ── THE INLINE-STYLE PROBLEM ──────────────────────────────────────────
   VERIFIED IN A BROWSER, 8 Sep 2026. Every persona's TYPEFACE applied on
   every heading — Bricolage, Sora, Newsreader and Bitter all measured — but
   the WEIGHT did not: --p-head-wt read 800 under Wild while the h1 rendered
   at 300, because the React components set font-weight as an INLINE STYLE
   and an inline style beats any stylesheet rule short of !important. It is
   the same trap that hid the portal's narrow column behind maxWidth:'1400px'.

   Bricolage Grotesque at 300 is not what Wild means, so this is the one
   place the feature needs !important to keep its promise.

   HOUSE IS DELIBERATELY ABSENT from this list. It is the default and must
   stay byte-for-byte the site as it already looks; forcing its 400 onto
   headings the components draw at 300 would change the page for a visitor
   who chose 'leave it alone'. */
:root[data-persona]:not([data-persona="house"]) :is(h1, h2, h3) {
  font-weight: var(--p-head-wt) !important;
}

/* Comfort refuses hairline weights wherever they appear, including inline
   styles set elsewhere — at 18px on a phone in daylight, a 300 weight on a
   dark ground is the difference between reading and guessing. */
:root[data-persona="comfort"] body,
:root[data-persona="comfort"] p,
:root[data-persona="comfort"] li,
:root[data-persona="comfort"] span,
:root[data-persona="comfort"] div { font-weight: max(400, var(--p-body-wt)); }

:root[data-persona="comfort"] p,
:root[data-persona="comfort"] li { line-height: var(--p-lh); }

/* ── THE SWITCHER ──────────────────────────────────────────────────────
   Bottom-left, and it fades with every other floating control when the
   footer arrives (body.at-footer, tssa-footer-fade).

   THE 126px IS MEASURED, NOT GUESSED. The "where am I?" guide button sits
   at bottom:74px and is 42px tall, so it occupies up to 116px from the
   bottom edge. The first version of this used 74px too and landed exactly
   on top of it — verified in a browser at 1280x720, both rects ending at
   y=646. 126 leaves a 10px gap. If the guide button ever moves, this
   follows it. */
.pers-btn {
  position: fixed; left: 18px; bottom: 126px; z-index: 855;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: 999px; cursor: pointer;
  background: rgba(12, 11, 8, .82); backdrop-filter: blur(14px);
  border: 1px solid var(--b1, rgba(255,255,255,.12));
  color: var(--t2, #ddd); font-family: var(--sans); font-size: 11.5px;
  letter-spacing: .04em; line-height: 1;
  transition: opacity .3s, transform .18s, border-color .18s;
}
.pers-btn:hover { transform: translateY(-1px); border-color: var(--p-accent) }
.pers-btn .pers-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--p-accent); box-shadow: 0 0 0 1px rgba(0,0,0,.25) inset;
}

.pers-panel {
  position: fixed; left: 18px; bottom: 170px; z-index: 856;
  width: min(310px, calc(100vw - 36px));
  background: rgba(12, 11, 8, .95); backdrop-filter: blur(22px);
  border: 1px solid var(--b1, rgba(255,255,255,.12));
  border-radius: 16px; padding: 14px;
  /* MEASURED: under Comfort this panel stands 551px tall, because the persona
     enlarges its own switcher -- correct, but it left 7px of headroom at
     1280x720 and would have started at -46 on a 667px phone, hiding the first
     two options from the very visitor who chose the large-type setting. */
  max-height: calc(100vh - 200px); overflow-y: auto; overscroll-behavior: contain;
  opacity: 0; visibility: hidden; transform: translateY(8px);
  transition: opacity .22s, transform .22s, visibility .22s;
}
.pers-panel.open { opacity: 1; visibility: visible; transform: none }

.pers-head {
  font-size: 9.5px; letter-spacing: .2em; text-transform: uppercase;
  color: var(--gold, #C9A84C); font-weight: 600; margin-bottom: 4px;
}
.pers-sub { font-size: 11.5px; color: var(--t3, #999); line-height: 1.5; margin-bottom: 12px }

.pers-opt {
  display: flex; align-items: flex-start; gap: 10px; width: 100%;
  padding: 9px 10px; margin-bottom: 4px; cursor: pointer; text-align: left;
  background: transparent; border: 1px solid transparent; border-radius: 10px;
  color: var(--t2, #ddd); font-family: inherit; transition: background .16s, border-color .16s;
}
.pers-opt:hover { background: rgba(255,255,255,.05) }
.pers-opt[aria-pressed="true"] { border-color: var(--b2, rgba(201,168,76,.4)); background: rgba(201,168,76,.08) }
.pers-opt .d { width: 11px; height: 11px; border-radius: 50%; margin-top: 3px; flex: none }
.pers-opt .n { font-size: 13px; line-height: 1.25 }
.pers-opt .w { font-size: 10.5px; color: var(--t4, #7a7466); letter-spacing: .08em; text-transform: uppercase; margin-left: 6px }
/* display:block, not inline -- margin-top does nothing on an inline box, so the
   blurb used to run straight on from the audience label: 'TEENSLoud, fast'. */
.pers-opt .b { display: block; font-size: 11.5px; color: var(--t3, #999); line-height: 1.45; margin-top: 2px }

/* AN IMMERSIVE ROUTE GETS NO SWITCHER. On /explore the whole viewport is a
   separate document in an iframe, so a persona cannot reach the type inside it
   anyway -- and the open panel measured 18-328 x 127-638, straight over RAH's
   own layer deck at 14-204 x 72-360. :has() rather than a pathname check
   because this script is appended to document.body once and outlives every
   client navigation, so it never sees the route change; CSS re-evaluates on
   its own. */
body:has(main[data-immersive]) .pers-btn,
body:has(main[data-immersive]) .pers-panel { display: none }

/* The floating rule the whole site follows: nothing floats over the footer. */
body.at-footer .pers-btn,
body.at-footer .pers-panel { opacity: 0; pointer-events: none }

@media (max-width: 720px) {
  .pers-btn { bottom: 120px; padding: 8px 12px; font-size: 11px }
  .pers-panel { bottom: 162px }
}

@media (prefers-reduced-motion: reduce) {
  .pers-btn, .pers-panel { transition: none }
}
