/* base.css — the platform's global rules: the reset, the mobile input floor, placeholder
   colour, the flash and field-error blocks, and the site footer. They lived at the foot of
   tokens.css until 2026-10-03, which made tokens.css unloadable anywhere that did not want
   them (the Filament panel, /dashboard, the Office taskpane, billing success): linking it
   for its values imposed box-sizing, the placeholder ink and the 640 input floor on pages
   that never had them. tokens.css is now values only; this file is linked immediately
   after it on every page that linked it before, so the cascade is unchanged. */

/* ═══ Global reset / mobile foundation ══════════════════════════════
   Loaded on every page that extends a layout (partials/_head-base.blade.php and
   layouts/participant.blade.php link it, as does errors/_shell). Layout-only:
   no colour/typography token VALUES are touched here, so mobile renders
   byte-identical colour/type to desktop; only the box model + width
   backstops change.

   box-sizing flip is the ROOT-CAUSE fix for width+padding overflow —
   it was previously applied ad-hoc at ~9 sites in templates.css. The
   only fixed-width+padding rule that shifts under the flip is
   .dm-td-summary (140px table cell, inside an overflow-x:auto wrapper);
   every other fixed-width rule is padding:0 or already border-box.
   'table' is deliberately EXCLUDED from the media backstop: results
   tables live in overflow-x:auto wrappers and are meant to exceed 100%
   and scroll, not squish. overflow-wrap:break-word kills long unbroken
   strings (URLs / flow tokens) as an overflow source globally. */
*, *::before, *::after { box-sizing: border-box; }
/* `hidden` wins over any class's display. The UA's own [hidden] rule loses to every author
   rule, so a class setting display showed hidden elements (docs/reality-register.md RR-166). */
[hidden] { display: none !important; }
img, svg, canvas, video { max-width: 100%; }
body { overflow-wrap: break-word; }

/* ── Mobile breakpoint convention (SINGLE SOURCE) ───────────────────
   Two phone tiers, converged from ~10 ad-hoc widths, aligned to the
   container-width vocabulary above (--participant-column 720, info form
   540, intro 640):
     640px — phone/tablet: single-column, full-bleed. The primary
             boundary; absorbs the old 560 / 600 / 620 / 639 queries.
     480px — small-phone tightening tier.
   Deliberately KEPT (these gate genuine desktop multi-column layout,
   NOT a phone boundary — do not fold into 640/480):
     768 / 1024   — home-v2 + method desktop hero / nav breakpoints.
     900 / 820 / 821 — workshop-stage desktop side-panel grid.
   NB: CSS media queries cannot read var(), so the breakpoints are
   documented constants, not tokens. Spacing inside them routes through
   --space-*; colours stay semantic. */
@media (max-width: 640px) {
  /* iOS focus-zoom floor: guarantee AT LEAST 16px on anything focusable so
     focusing it doesn't zoom the page. checkbox/radio/range are excluded
     (font-size is meaningless there).

     [HARD] IT IS A MINIMUM, NOT A FIXED SIZE (2026-09-17), AND max() IS WHY.
     It used to declare a flat `font-size:16px`, which at (0,3,1) beat every
     tier on the surface — so a field asking for MORE than 16 was cut down to
     16 on a phone. That was invisible while every tier asked for exactly 16;
     `--tpl-field-size` going to 18px made it visible, as a tier rendering its
     inputs at 16 and its textareas at 18 (the `select, textarea` arm below is
     (0,0,1) and loses, so textareas escaped).

     LOWERING THE SPECIFICITY WAS THE WRONG FIX AND WAS REJECTED. This rule has
     to keep beating things like `.tpl-start .tpl-weight-step-input` (0,2,0),
     which asks for 12px and RELIES on losing here — the 2026-08-31 pass deleted
     every rule that reached under this floor and measured that none was left.
     A floor that stops winning re-opens exactly that.

     So the rule still wins and the VALUE carries the intent: a field that wants
     to be larger than the floor says so by declaring `--tpl-field-min` on
     itself, and max() takes the larger. Unset, the fallback is 0px and the
     result is a flat 16px — identical to the old behaviour for everything that
     has not opted up. `.tpl-field-text` (templates.css) is the only tier that
     declares it today.

     [HARD] SPECIFICITY IS UNCHANGED BY THAT EDIT — only the value moved.
     [HARD] SPECIFICITY: the `input:not([type=…]):not(…):not(…)` selector is
     (0,3,1) — each :not([attr]) adds a class-level (0,1,0), NOT the (0,0,1)
     a "bare element" reading suggests. So a class-scoped size like
     `.tpl-start input.tpl-foo` (0,2,1) LOSES to this and the input stays 16px.
     Any rule meant to shrink an <input> below 16px on mobile MUST exceed
     (0,3,1) (e.g. add a class/id/`:not()` to reach (0,4,1) / (1,x,y)) — see
     the facilitator-input + weight-stepper overrides in start.blade.php. The
     bare `select, textarea` arm is only (0,0,1); those shrink freely.

     [HARD] AND SO DOES AN INPUT, IF THE RULE THAT SHRINKS IT EXCEEDS (0,3,1) — WHICH
     IS WHAT RR-109 ACTUALLY IS (measured 2026-09-19, and it is NOT what that entry
     says). `php artisan setup:field-focus` reports three FAILs on MS, survey and quiz;
     all three are ONE element, `<input type="datetime-local" name="closes_at"
     class="tpl-mono">`, and the rule that beats this floor is
     `.tpl-start.setup-sidebar .tpl-sidebar input[type="datetime-local"]`
     (setup-sidebar.css) at (0,4,1). RR-109 named question-types.js's guidance
     <textarea> and `.tpl-mono` at (0,1,0); that textarea also carries `.tpl-field-text`
     (0,2,0) and renders at 18px, so it was never under the floor at all. The fix is in
     setup-sidebar.css, where the rule that out-specifies lives — which is exactly what
     this probe's own failure message has been saying.

     THE OTHER LIVE INSTANCE THE PROBE COULD NOT SEE: its census selector is
     `.tpl-start input…, .tpl-start textarea` and does not include `select`. Three
     `select.tpl-mono` controls in the time/date config rendered 12px at 390, beaten
     there by `.qt-subcard select` (question-types.css, (0,1,1), later in source order
     than this file). Fixed in that file, and the probe now censuses `select` so the
     class is observable. */
  input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
  select, textarea { font-size: max(16px, var(--tpl-field-min, 0px)); }
}

/* ── Placeholder text (platform-wide) ───────────────────────────────
   Grey is for ::placeholder only. A field holding a value — typed, or
   seeded from a template via data-default — renders it in ink. */
input::placeholder,
textarea::placeholder{color:var(--ink);}

/* Standard content canvas — pairs the canvas-width token with the
   centering rule. Pages with extra inline padding/flex still set
   max-width directly via var(--canvas-width); use this class when
   max-width + margin auto is the entire wrapper rule. */
.canvas { max-width: var(--canvas-width, 900px); margin: 0 auto; }

/* Required-field marker — single source for the red asterisk that
   appears next to every required label across every form on the
   platform. Apply .field-required to the LABEL element (alongside
   any other label class like .field-label); ::after inserts the
   asterisk so the markup stays clean. Uses var(--accent) as the
   project's red token (defined above in :root).

   For mode-conditional required fields (e.g. group_name only required
   in Group mode), toggle the class with the field's visibility — never
   leave the asterisk on a hidden field. */
.field-required::after {
  content: "*";
  color: var(--accent);
  /* Superscript marker appended inline right after the label text, so its offset
     from the last character is constant for every label regardless of length
     (.tpl-mono / .field-label carry no letter-spacing, and vertical-align shifts
     only vertically). No margin — it sits right up against the text; font-size:0.9em
     keeps it clearly legible; vertical-align:super raises it to the top-right corner. */
  font-size: 0.9em;
  vertical-align: super;
}

/* THE ONE MESSAGE COMPONENT (partials/flash.blade.php renders the session flashes; any page
   may write the same markup). A message about the state of a page, session or account is
   .flash plus ONE kind; the kind sets the edge and the tint and nothing else. The body is in
   the body font and renders as written; only a tag and a title are uppercase mono. */
.flash{font-family:var(--font-body);font-size:var(--type-field);line-height:var(--type-note-line-loose);color:var(--color-text);padding:var(--inset-box) var(--inset-panel);border-left:3px solid;border-radius:2px;margin-bottom:var(--space-lg);}
.flash--success{border-left-color:var(--success);background:rgba(var(--success-rgb),0.08);}
.flash--info{border-left-color:var(--info);background:var(--info-bg);}
.flash--warn{border-left-color:var(--warn);background:var(--warn-bg);}
.flash--error{border-left-color:var(--error-red);background:rgba(var(--error-rgb),0.06);}
/* A message's parts: a tag, a heading line, further lines, a list, its actions, a dismiss. */
.flash__tag,
.flash__title{font-family:var(--font-mono);font-size:var(--type-note);text-transform:uppercase;}
.flash__tag{margin-right:var(--gap-row);}
.flash__title{display:block;}
.flash p{margin:var(--space-xs) 0 0;}
.flash ul{margin:var(--space-xs) 0 0;padding-left:1.25rem;}
.flash__action{color:inherit;text-decoration:underline;text-underline-offset:2px;white-space:nowrap;margin-left:var(--gap-row);}
.flash__actions{display:block;margin-top:var(--space-xs);}
.flash__actions > .flash__action:first-child{margin-left:0;}
.flash__dismiss{float:right;background:none;border:0;padding:0 0 0 var(--gap-row);font:inherit;font-size:1.4em;line-height:1;color:inherit;cursor:pointer;}
/* A message on the page rather than a banner: no edge, no tint, centred, the tick disc above
   (the same --quiz-tick-svg over --quiz-correct the setup page paints on a completed field).
   The text wraps at its own 44ch measure, so a long message never runs the full canvas. */
.flash--celebrate{text-align:center;border-left:none;background:none;border-radius:0;padding:var(--inset-box) 0;}
.flash--celebrate > [data-flash-text],
.flash--celebrate > .tpl-sublabel{display:block;max-width:44ch;margin-left:auto;margin-right:auto;line-height:1.25;}
.flash--celebrate-icon{display:block;width:40px;height:40px;margin:0 auto var(--space-sm);border-radius:50%;background-color:var(--quiz-correct);background-image:var(--quiz-tick-svg);background-repeat:no-repeat;background-position:center;background-size:27px 27px;}

/* THE ONE FIELD ERROR: a message attached to a single form field, directly under it. */
.field-error{font-family:var(--font-mono);font-size:var(--type-caption);color:var(--error-red);margin-top:var(--space-xs);}

/* Site footer — shared across every page that extends
   layouts/participant.blade.php. Single centred row of nav links
   above a muted copyright line, on the platform's dark ink.
   --footer-bg and the three on-dark alpha values below were literals
   local to this band until D-DEBT-99 item 10 (docs/known-debt.md):
   under a [data-theme] slate proof the whole site went slate and this
   band stayed brown-black, because nothing here read a token. Minted
   rather than pointed at --on-ink/--on-ink-muted, which are close but
   not equal (0.6 vs this band's 0.55/0.92/0.3) — reusing them would
   have moved the footer's own values, which item 10 did not ask for.
   The 0.08 border alpha is left a literal; it is a structural
   hairline, not one of the three colour roles the item named. */
.site-footer {
  background: var(--footer-bg);
  border-top: 1px solid rgba(255,255,255,0.08);
  padding: 28px 24px;
  margin-top: 48px;
  text-align: center;
}
.site-footer-nav {
  display: inline-flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 28px;
}
/* A 24px HIT AREA, WITH THE 11px TYPE UNTOUCHED (2026-09-20). The links measured
   43-180 x 14 on the rendered DOM — under the 24x24 floor on their short axis, on
   every page of the participant flow and of the platform (flow audit §1.5). The
   type size, the letter-spacing, the colour and the absence of any painted box are
   all unchanged: inline-flex + min-height grows the BOX the pointer lands on and
   centres the same glyphs inside it. The band itself gets 10px taller, which is the
   one visible consequence and is the point of the change. */
.site-footer-link {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  font-family:var(--font-mono);
  font-size: var(--type-badge);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--footer-link);
  text-decoration: none;
  transition: color 0.15s ease;
}
.site-footer-link:hover,
.site-footer-link:focus-visible {
  color: var(--footer-link-hover);
}
.site-footer-copy {
  margin-top: var(--inset-panel);
  font-family:var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--footer-copy);
}
@media (max-width: 480px) {
  .site-footer-nav { gap: var(--inset-panel); }
}
