/* ============================================================================
   brand.css — RowOn Beach Sprint Cup Series app layer
   v2.0. Now sits on the Row Ontario design system rather than redefining it.

   ro-tokens.css owns the tokens, the base element styles (type scale, links,
   form controls, focus rings) and a set of ro-prefixed components. This file
   owns only what is specific to this app:

     1. Aliases for the token names the fourteen pages already reference.
     2. This app's own component classes — .app-header, .tile, .table-wrap,
        .ro-load — declared on system tokens.
     3. The phone-first page width, which is this app's own decision: it is
        used one-handed, outdoors, on a beach.

   The system's components are namespaced ro-* precisely so they cannot collide
   with names a page already uses. That matters here: timing.html uses .row for
   a lane row, and an unprefixed .row utility in a shared stylesheet silently
   forced display:flex onto it and broke the lane cards.

   Do not add new tokens here. If something is missing, it belongs in
   ro-tokens.css so the rest of the build inherits it.
   Previous version archived at _archive/brand.css.pre-design-system-2026-07-31.
   ========================================================================== */

@import "ro-tokens.css";

/* Every page carries data-density="compact" on <html>, which steps the heading
   tokens down one rung of the same 1.25 scale so more fits on a phone held at
   arm's length in the sun. The ratios that create hierarchy are unchanged. */

:root{
  /* ---- aliases: names the fourteen pages already use ----
     Keeping these meant no page-level CSS had to change when the system
     landed. New work should use the ro-tokens names directly. */
  --ro-soft:var(--ro-neutral);
  --ro-radius:var(--radius);
  --ro-radius-sm:var(--radius-sm);
  --ro-font:var(--font);

  /* State washes. The system names them --ro-yellow-*; the pages say amber. */
  --ro-amber-bg:var(--ro-yellow-bg);
  --ro-amber-border:var(--ro-yellow-line);
  --ro-amber-ink:var(--ro-yellow-ink);
  --ro-green-border:var(--ro-green-line);
  --ro-blue-border:var(--ro-blue-line);
}

/* ---------- page width ----------
   Phone-first. The primary viewport is 390px and most screens are read
   one-handed. Wider than ~720px and the eye loses the line on a roster. */
.page{width:100%;max-width:480px;margin-inline:auto;padding:var(--s2) var(--s2) var(--s6);}
@media (min-width:700px){.page{max-width:720px;}}
@media (min-width:1000px){.page--wide{max-width:1100px;}}

/* ---------- .app-header — this app's .ro-brandbar ----------
   Same component, same rules: one mark at exactly one body line so it locks to
   the title, back link, title, mode chip pushed right. */
.app-header{display:flex;align-items:center;gap:var(--s1) var(--s2);flex-wrap:wrap;
  background:var(--ro-red);color:#fff;padding:var(--s2);
  border-radius:var(--radius);margin-bottom:var(--s2);}
/* Two rows below 560px, so trim the vertical padding to pay for the second one. The Back link
   keeps its full 48px tap target - its padding is inline, not block - so nothing gets harder to
   hit. Net effect against the old single-row header: 80px with a two or three line title
   becomes 96px with a one-line title on every page. */
@media (max-width:559px){ .app-header{padding:var(--s1) var(--s2);row-gap:0;} }
.app-header__mark{flex-shrink:0;height:var(--line-1);width:auto;display:block;}
/* The most-tapped control in the app, and it was 21px tall - a text link with no box.
   The touch minimum is 48px and this one gets pressed outdoors, one-handed, sometimes in
   gloves. The negative inline margin keeps it looking the same distance from the mark while
   the tap target extends past the text on both sides. */
.app-header__back{display:inline-flex;align-items:center;min-height:var(--line-2);
  padding-inline:var(--s1);margin-inline:calc(var(--s1) * -1);
  color:#fff;text-decoration:none;font-weight:700;
  font-size:var(--fs-small);opacity:.9;flex-shrink:0;}
.app-header__back:hover,.app-header__back:focus-visible{opacity:1;color:#fff;}
/* The title used to share the first row with the mark, the 48px Back target and the mode chip,
   which left it 125px of a 375px screen - a third of the width - so "Volunteer management",
   "My volunteer page", "Volunteer sign-up", "Series management" and "Organisational structure"
   all wrapped, and my.html ran to three lines. The header is already flex-wrap:wrap, so giving
   the title its own full-width row below the controls costs one line instead of two or three
   and needs no page renamed. Above 560px there is room for everything on one row. */
.app-header__title{flex:1 1 100%;order:2;min-width:0;margin:0;color:#fff;
  font-size:var(--fs-1);font-weight:900;line-height:var(--line-1);letter-spacing:-0.005em;}
.app-header__mark,.app-header__back{order:1;}
.app-header .chip{order:1;margin-left:auto;}
@media (min-width:560px){
  .app-header__title{flex:1 1 auto;order:1;}
  .app-header .chip{order:2;}
}

/* ---------- .chip ----------
   ui.js builds these class names at runtime (`"chip chip-" + mode`), so they
   cannot simply be renamed in the markup. Height is one body line so the chip
   locks to the header title beside it. */
.chip{display:inline-flex;align-items:center;gap:6px;height:var(--line-1);
  font-size:var(--fs-caption);font-weight:700;line-height:1;letter-spacing:.06em;
  text-transform:uppercase;padding:0 10px;border-radius:999px;
  border:1px solid var(--hairline);background:var(--panel-tint);color:var(--fg-dim);}
.chip:empty{display:none;}
.chip-demo{background:var(--ro-yellow-bg);border-color:var(--ro-yellow-line);color:var(--ro-yellow-ink);}
.chip-live{background:var(--ro-green-bg);border-color:var(--ro-green-line);color:#00743a;}
.chip-stale{background:var(--panel-tint);border-color:var(--hairline);color:var(--fg-dim);}

/* ---------- .tile — this app's .ro-card--link ---------- */
.tile-grid{display:grid;grid-template-columns:1fr;gap:var(--s2);margin-top:var(--s2);}
@media (min-width:480px){.tile-grid{grid-template-columns:1fr 1fr;}}
@media (min-width:820px){.tile-grid{grid-template-columns:1fr 1fr 1fr;}}
.tile{display:block;background:var(--panel-bg);border:1px solid var(--hairline);
  border-radius:var(--radius);padding:var(--s2);text-decoration:none;color:inherit;
  transition:border-color .15s ease;}
.tile:hover,.tile:focus-visible{border-color:var(--ro-red);color:inherit;}
.tile:active{transform:translateY(1px);}
.tile__title{font-size:var(--fs-0);font-weight:900;color:var(--fg);line-height:1.3;}
.tile__desc{font-size:var(--fs-caption);color:var(--fg-dim);margin-top:4px;}

/* ---------- .btn ----------
   Pages write `class="btn primary"`, not the system's `ro-btn ro-btn--primary`.
   48px is the touch minimum: these are pressed outdoors, sometimes in gloves.
   .sm drops to 24px and is only used on the timing board's lane adjustments,
   which are a desk task on a paired device. */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--s1);
  min-height:var(--line-2);padding:var(--s1) var(--s3);
  font:inherit;font-weight:700;font-size:var(--fs-0);line-height:1.2;
  background:var(--panel-bg);color:var(--fg);border:1px solid var(--hairline);
  border-radius:var(--radius-sm);cursor:pointer;text-decoration:none;text-align:center;}
.btn:hover{border-color:var(--fg);color:var(--fg);}
.btn:active{transform:translateY(1px);}
.btn:disabled,.btn[aria-disabled="true"]{opacity:.45;cursor:default;transform:none;}
.btn.primary{background:var(--ro-red);border-color:var(--ro-red);color:#fff;}
.btn.primary:hover{background:var(--ro-red-2);border-color:var(--ro-red-2);color:#fff;}
.btn.ghost{background:var(--ro-paper);}
.btn.danger{background:var(--ro-red-2);border-color:var(--ro-red-2);color:#fff;}
.btn.sm{min-height:var(--line-1);height:var(--line-1);padding:0 var(--s2);font-size:var(--fs-small);}
.btn.block{display:flex;width:100%;}

/* ---------- fields ---------- */
.field{margin:var(--s1) 0;}
.field-note{font-size:var(--fs-caption);color:var(--fg-dim);margin-top:4px;}
.field-row{display:flex;gap:var(--s1);align-items:center;flex-wrap:wrap;margin:var(--s1) 0;}

/* ---------- tables ---------- */
.table-wrap{width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;}
table{width:100%;border-collapse:collapse;font-size:var(--fs-small);}
th{font-size:var(--fs-caption);font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--fg-dim);text-align:left;padding:var(--s1);
  border-bottom:1px solid var(--hairline);}
/* nowrap only inside the scroll container. A bare table with no .table-wrap has
   nowhere to overflow to, so unwrappable headers push the whole page sideways:
   that is what happened to spectator.html's round tables at 375px. */
.table-wrap th{white-space:nowrap;}
td{padding:var(--s1);border-bottom:1px solid var(--hairline);vertical-align:top;}
td.num,th.num{text-align:right;font-variant-numeric:tabular-nums;}

/* ---------- .card ----------
   Card titles are labels on an operational board, not section headings. The
   element is <h2> across the pages, so the size is set on the descendant
   rather than on a class the markup does not carry. */
.card{background:var(--panel-bg);border:1px solid var(--hairline);
  border-radius:var(--radius);padding:var(--s2);margin-top:var(--s2);}
.card > :last-child{margin-bottom:0;}
.card h2{font-size:var(--fs-0);font-weight:900;line-height:1.3;letter-spacing:0;
  margin:0 0 var(--s1);}

/* ---------- .ro-load — this app's .ro-loading ---------- */
.ro-load{display:flex;align-items:center;gap:var(--s2);padding:var(--s2) 0;
  font-size:var(--fs-small);font-weight:700;color:var(--fg-dim);}
.ro-load::before{content:"";flex-shrink:0;width:var(--s4);height:4px;border-radius:2px;
  background:var(--ro-red);animation:ro-pulse 1.1s ease-in-out infinite;}
@media (prefers-reduced-motion:reduce){.ro-load::before{animation:none;opacity:.8;transform:none;}}

/* ---------- .sbar — the series shell bar (built by shared/ui.js renderSeriesBar) ----------
   Sits directly under the header on an event page, and only for a session the server has
   confirmed holds a series grant.

   It is a shelf, not a second identity block. The red .app-header above it is this screen's
   committed colour, so the bar stays on the neutral tint and keeps red for the two things
   that are actually interactive. A second red block would halve the header's commitment and
   read as two competing headers.

   It carries NO Row Ontario mark. The header already has the one mark a screen may have.

   Everything here is on the 8px spacing grid, both controls are var(--line-2) = 48px, and
   the only uppercase is the two 12px labels tracked to +.06em. */
.sbar{margin:0 0 var(--s2);padding:var(--s1) var(--s2) var(--s2);
  background:var(--panel-tint);border:1px solid var(--hairline);border-radius:var(--radius-sm);}
.sbar__now{display:flex;align-items:baseline;gap:var(--s1) var(--s2);flex-wrap:wrap;
  margin:0;min-height:var(--line-1);}
.sbar__eyebrow{flex-shrink:0;font-size:var(--fs-eyebrow);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--fg-dim);line-height:var(--line-1);}
.sbar__cup{min-width:0;font-size:var(--fs-0);font-weight:900;line-height:var(--line-1);
  color:var(--fg);}
.sbar__go{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s1);}
.sbar__label{flex:0 0 auto;font-size:var(--fs-eyebrow);font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--fg-dim);}
/* width:auto overrides the system's width:100% on select so it can flex; min-width:0 stops
   a flex item's automatic minimum size from pushing the row past 375px. */
.sbar__pick{flex:1 1 auto;min-width:0;width:auto;height:var(--line-2);}
.sbar__foot{display:flex;align-items:center;gap:var(--s1) var(--s2);flex-wrap:wrap;margin-top:var(--s1);}
.sbar__season{flex:0 0 auto;background:var(--ro-paper);padding:var(--s1) var(--s2);}
.sbar__who{flex:1 1 auto;min-width:0;font-size:var(--fs-caption);line-height:var(--line-1);
  color:var(--fg-dim);}

/* ---------- .rr - role resources (shared/role-resources.js renderResourcesHtml) ----------
   Sits at the foot of a role card on roles.html and my.html. Need-to-knows render open because
   they are the floor and they work offline; the links sit inside a closed <details> because
   every one of them needs a connection.

   Attribution chips are deliberately quiet. They must be readable enough that someone can tell
   an RCA rule from a World Rowing one - which matters, the two disagree about buoy misses - but
   they are not the content, so they never outweigh the bullet they sit against. */
.rr{margin-top:var(--s3);padding-top:var(--s2);border-top:2px solid var(--ro-red);}
.rr__title{font-size:var(--fs-0);font-weight:900;color:var(--fg);margin:0 0 var(--s1);
  text-transform:none;letter-spacing:0;}
.rr-need{list-style:none;margin:0;padding:0;}
.rr-need li{position:relative;padding-left:var(--s3);margin:var(--s1) 0;
  font-size:var(--fs-small);line-height:1.5;}
.rr-need li::before{content:"";position:absolute;left:0;top:.55em;
  width:8px;height:8px;border-radius:2px;background:var(--ro-red);}
.rr-src{font-size:var(--fs-caption);font-weight:700;color:var(--ro-red-2);
  text-decoration:underline;white-space:nowrap;}
/* Row Ontario's own SOPs have no public URL. Saying "event SOP" in plain, unlinked text is
   honest about that; styling it like the others would invite a tap that goes nowhere. */
.rr-src--internal{color:var(--fg-dim);text-decoration:none;font-style:italic;}

/* the attribution chip, styled by AUTHORITY rather than by which body it is.
   Iain, 2026-08-02: "We do not follow WR rules; they are just to help with added context. We are
   following the rules and regulations from Rowing Canada, Row Ontario, and Rowan's Law."
   An earlier version gave World Rowing the same red chip as Rowing Canada, which said the two
   carried equal authority. They do not, and on a role card that is a governance error, not a
   styling one. */
.rr-body{display:inline-flex;align-items:center;gap:5px;height:20px;padding:0 8px;
  border-radius:999px;font-size:var(--fs-eyebrow);font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;white-space:nowrap;vertical-align:middle;
  background:var(--panel-tint);border:1px solid var(--hairline);color:var(--fg-dim);}
/* Rowing Canada, Row Ontario and Rowan's Law: these are the rules we race under. */
.rr-body--governing{background:#FFF3F4;border-color:var(--ro-red);color:var(--ro-red-2);}
/* NCCP: education, not a rule. Neutral. */
.rr-body--training{background:var(--panel-tint);border-color:var(--hairline);color:var(--fg-dim);}
/* World Rowing: context only, and it says so on its face. Dashed border so it does not read as
   an authority even at a glance across a sunlit screen. */
.rr-body--context{background:transparent;border-style:dashed;border-color:var(--hairline);
  color:var(--fg-dim);}
.rr-body__note{font-style:normal;font-weight:700;opacity:.75;text-transform:lowercase;
  letter-spacing:0;}

/* the whose-rules-are-these notice, shown whenever World Rowing appears in a block */
.rr-gov{margin:var(--s2) 0 0;padding:var(--s1) var(--s2);
  background:var(--panel-tint);border-left:3px solid var(--ro-red);border-radius:var(--radius-sm);
  font-size:var(--fs-caption);color:var(--fg-dim);line-height:1.5;}

.rr-deep{margin-top:var(--s2);}
.rr-deep summary{cursor:pointer;min-height:var(--line-2);display:flex;align-items:center;
  font-size:var(--fs-small);font-weight:800;color:var(--ro-red-2);}
.rr-deep summary:hover,.rr-deep summary:focus-visible{color:var(--ro-red);}
.rr-links{list-style:none;margin:var(--s1) 0 0;padding:0;}
.rr-link{padding:var(--s1) 0;border-bottom:1px solid var(--hairline);}
.rr-link:last-child{border-bottom:0;}
.rr-link a{font-size:var(--fs-small);font-weight:700;}
.rr-link__meta{display:inline-flex;align-items:center;gap:6px;margin-left:var(--s1);}
.rr-mins,.rr-free{font-size:var(--fs-eyebrow);font-weight:800;letter-spacing:.04em;
  text-transform:uppercase;color:var(--fg-dim);}
.rr-free{color:#00743a;}
.rr-link__note{display:block;font-size:var(--fs-caption);color:var(--fg-dim);margin-top:2px;}
.rr-hostnote{font-size:var(--fs-caption);color:var(--fg-dim);margin:var(--s2) 0 0;}

/* Printed role cards keep the need-to-knows and the attribution, which is the part that is
   useful on paper at the volunteer table, and open the links list rather than hiding it inside
   a collapsed disclosure that prints as a bare summary line. */
@media print{
  .rr-deep[open] .rr-links,.rr-deep .rr-links{display:block;}
  .rr-deep summary{color:var(--fg);}
}

/* ---------- land acknowledgement ----------
   Sits directly above the DRAFT footer, built by shared/ui.js renderLandAcknowledgement()
   from the venue of the current ?e= event.

   Deliberately NOT fine print. Row Ontario's own guidelines open by saying an
   acknowledgement "is not a box to check off a list", so it reads at body size with a
   committed red rule down the side, not at caption size in the footer line. The red rule is
   the brand's "fine lines as an organising device" doing the work a heading colour would
   otherwise have to, without adding a second red block to the page.

   It prints. That is the point: a printed roster or role card carries it too. */
.land-ack{max-width:480px;margin:var(--s3) auto 0;padding:var(--s1) 0 var(--s1) var(--s2);
  border-left:2px solid var(--ro-red);}
.land-ack__title{font-size:var(--fs-eyebrow);font-weight:800;letter-spacing:.06em;
  text-transform:uppercase;color:var(--fg-dim);margin:0 0 2px;line-height:1.2;}
/* --fs-caption (12px) is the floor: Row Ontario's own standard is "12px on screen, never
   smaller", so this is as quiet as the block can get without breaking their brand rule. */
.land-ack__text{font-size:var(--fs-caption);line-height:1.45;color:var(--fg-dim);margin:0;}
/* No opacity. An .85 here measured 3.94:1 against a 4.5 requirement - the same mistake this
   stylesheet's hero rules were fixed for earlier the same day. Italic carries the
   de-emphasis; the colour is already --fg-dim. */
.land-ack__pending{font-size:var(--fs-caption);color:var(--fg-dim);margin:2px 0 0;font-style:italic;}

/* ---------- DRAFT footer ---------- */
.app-footer{max-width:480px;margin:var(--s3) auto 0;padding:var(--s2) 0 0;
  font-size:var(--fs-caption);color:var(--fg-dim);
  border-top:1px solid var(--hairline);text-align:center;}
/* The only demo marking that survives printing: brand.css hides .chip in @media print,
   so without this a roster printed in demo mode looks exactly like a real one. */
.app-footer__demo{color:var(--ro-red-2);font-weight:800;}

/* In-development note and feedback box (2026-08-04). Sits under the DRAFT line in the footer on
   every page. --fs-caption (12px) is the floor Row Ontario's standard sets and this must not go
   below it; the note is small but it still has to be readable on a beach. */
.app-dev{max-width:480px;margin:var(--s2) auto 0;padding-top:var(--s2);
  border-top:1px solid var(--hairline);text-align:left;}
.app-dev__note{font-size:var(--fs-caption);color:var(--fg-dim);margin:0 0 var(--s1);}
.app-dev__box>summary{min-height:48px;display:flex;align-items:center;cursor:pointer;
  font-size:var(--fs-caption);font-weight:800;color:var(--ro-red);list-style:none;}
.app-dev__box>summary::-webkit-details-marker{display:none;}
.app-dev__box>summary::before{content:"";flex:none;width:7px;height:7px;margin-right:8px;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;
  transform:rotate(45deg);margin-bottom:3px;}
.app-dev__box[open]>summary::before{transform:rotate(-135deg);margin-bottom:0;}
.app-dev__box>summary:focus-visible{outline:2px solid var(--ro-red);outline-offset:2px;}
.app-dev__text{width:100%;box-sizing:border-box;font:inherit;font-size:var(--fs-body);
  padding:var(--s1);border:1px solid var(--hairline);border-radius:var(--ro-radius);
  background:var(--bg);color:var(--fg);resize:vertical;}
.app-dev__row{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s1);}
.app-dev__said{font-size:var(--fs-caption);color:var(--fg-dim);}
.app-dev__priv{font-size:var(--fs-caption);color:var(--fg-dim);margin:var(--s1) 0 0;}
/* Never print the feedback box: on paper it is a dead control taking up a card. */
@media print{ .app-dev{display:none;} }

/* ---------- print ---------- */
@media print{
  .app-header,.chip,.no-print,.ro-load{display:none!important;}
  /* The footer is the last line of defence against a demo roster being handed out as real,
     so give the marking real weight on paper rather than letting it read as fine print. */
  .app-footer{font-size:11pt;}
  /* The acknowledgement prints with everything else - a printed roster, role card or org
     chart carries it too. break-inside so it is never split across two pages. */
  .land-ack{break-inside:avoid;page-break-inside:avoid;max-width:none;border-left:2pt solid #E4002B;}
  .land-ack__text{font-size:10pt;}
  .app-footer__demo{display:block;margin-top:2mm;font-size:13pt;color:#C82029;}
  body{background:#fff;}
  .print-page{page-break-after:always;}
  .print-page:last-child{page-break-after:auto;}
  @page{margin:12mm;}
}
