/* ---------------------------------------------------------------------------
   skiracing.nastar.com — local theme rules

   Deliberately NOT part of theme_2026/css/nastar.css. That file is the paired
   shared-chrome stylesheet (its counterpart is
   /home/nastar_com/public_html/theme/css/nastar.css) and the two must
   stay in step. Anything in here is specific to this application's markup --
   selectors like #article-content come from this site's legacy Drupal-era
   wrappers and do not exist on nastar.com -- so it does not belong there.

   Same precedent as legacy-form-control.css and legacy-bootstrap-grid.css,
   which are likewise linked from header_2026.jsp on this site only.

   Sizes are in px, not rem: legacy nastar_2019.css carries `* { font-size:14px }`,
   which lands on <html> too, so the root font here is 14px and rem cannot express
   sizes that match nastar.com's 16px root.
   --------------------------------------------------------------------------- */


/* --- Clearance for the overhanging logo badge ------------------------------

   .site-logo--badge (theme_2026/css/nastar.css) is position:absolute with
   top:-78px and a 173px-tall image, so it hangs *below* the header rather than
   sitting inside it. Measured on this site at 1024px:

       header bottom .......... 132px
       badge bottom ........... 177px
       overhang ................ 45px

   Page content began at exactly 132px -- flush with the header, zero clearance
   -- so the top of every page rendered underneath the badge. Because the badge
   is an opaque rectangular <a>/<img> at z-index 20, it both hid that content
   and swallowed clicks on it, which is why hovering a link there reported the
   badge's own href (https://www.nastar.com/) instead of the link's.

   The badge is absolutely positioned and therefore out of normal flow, so
   nothing can be pushed out of its way by changing the badge itself. The
   clearance has to be reserved by the content wrapper.

   48px rather than 45px: a few pixels of margin, and it matches the theme's
   existing --space-7 step so the value is not arbitrary.

   Scoped to >=992px because below that breakpoint the badge is display:none
   (see nastar.css .site-logo--badge), so there is nothing to clear and the
   space would be wasted on a phone.

   #article-content wraps the content of every page on this site -- verified
   present exactly once across nine sampled page types -- so this applies
   site-wide by design, not just to the race record page.                     */

@media (min-width: 992px) {
  #article-content { padding-top: 48px; }
}


/* --- Phone/tablet: release the IE-era fixed widths -------------------------

   Measured on the race record page at 390px: the document rendered 632px wide
   and scrolled sideways. 632 = 32px page margin + 600px, and the 600px comes
   from nastar_2019.css:

       .race-attributes-form-field       { width: 600px; }
       .race-attributes-form-field value { width: 375px; }

   Both carry the comment "need width for ie or it wraps" -- Internet Explorer
   workarounds from a browser that no longer needs supporting. On a 390px
   screen a 600px block simply cannot fit, so the whole document scrolls.

   Two inline `width:600px` styles on #comp2TabName and #comp2Body
   (comp2.jsp:84 and :87) contribute the same problem and need !important to
   override, since they are inline. Those would be better fixed at source; they
   are handled here for now so this change stays in one file and does not touch
   the fragile JavaScript-injected tab content.

   Deliberately scoped to <=991px. Desktop keeps today's rendering byte for
   byte -- this is a phone fix, not a re-layout, and the IE justification is
   irrelevant at both widths anyway.

   IMPORTANT -- these classes are also used by raceresults.jsp, which carries
   the standing requirement that wide race content keeps WHOLE-DOCUMENT
   horizontal scrolling and must never gain an inner scrolling container.
   Nothing here sets overflow, and nothing here touches the results tables:
   only the fixed pixel widths on the label/value pairs are released, so wide
   tables still push the document wide and still scroll as a whole.          */

@media (max-width: 991px) {
  .race-attributes-form-field {
    width: auto;
    max-width: 100%;
  }
  .race-attributes-form-field value {
    width: auto;
    max-width: 100%;
  }
  #comp2TabName,
  #comp2Body {
    width: auto !important;
    max-width: 600px;
  }
}


/* --- Badges page: release the legacy 600px table width ---------------------

   includes/badges.jsp opens two `<table width="600">` (the badge list and the
   single-badge detail view), both hard-coded from the same IE-era style as
   the .race-attributes-form-field fix above. Measured at 390px: document
   632px wide, scrolling sideways with nothing that needs the width -- unlike
   Team or Where To Race (doc/skiracing-open-issues.md item 32 / C8), this is
   ordinary badge-icon/description/list content, not inherently wide data.

   The global `img, svg, video { max-width:100% }` rule (nastar.css) already
   lets the 80px badge icons shrink to fit their cell, so simply releasing the
   forced width is enough: the table falls back to auto layout and shrinks to
   its content instead of forcing 600px onto a 390px screen. Verified in a
   real browser: 632px -> 383px document width, zero horizontal scroll, same
   badge-icon/description grid and racer-list columns as at 600px, just
   narrower.

   Scoped to <=991px, same boundary as the block above, so desktop keeps the
   existing fixed 600px table byte-for-byte. Class-scoped to `.badges-table`,
   not a generic `table[width="600"]` rule, so this cannot reach any other
   page's tables. */
@media (max-width: 991px) {
  .badges-table {
    width: 100%;
    max-width: 600px;
  }
}


/* ===========================================================================
   Race record header (includes/comp2.jsp)

   Replaces the old top zone, where three mutually exclusive controls sat
   inline beside the racer's name in a float:left div with a hard-coded 28px
   height -- the band the logo badge overhangs. See doc/skiracing-open-issues.md
   items 1, 2 and 9 for the measurements behind each decision here.

   px throughout, not rem: legacy nastar_2019.css carries `* { font-size:14px }`,
   which lands on <html> too, so rem cannot express sizes that match nastar.com.
   Tokens (--nastar-*, --gray-*, --space-*) come from theme_2026/css/nastar.css.
   =========================================================================== */
/* --- 2. Identity header --------------------------------------------------- */
.record-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4) var(--space-5);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid var(--gray-200);
  margin-bottom: var(--space-4);
}

.record-header__identity { min-width: 0; }

.record-header__name {
  font-family: var(--font-heading);
  font-size: 34px;
  line-height: 1.1;
  font-weight: 700;
  color: var(--gray-900);
  margin: 0 0 var(--space-1) 0;
}

.record-header__id {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray-500);
}

/* The action slot. Right-aligned inside the content container, which also
   keeps it clear of the badge horizontally: the badge is centered in the
   viewport and only 286px wide, so a right-aligned control in a ~1180px
   container never reaches it. */
.record-header__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  flex-shrink: 0;
}

.record-header__actions .btn { font-size: 14px; }

/* --- 3. Season stats + season picker -------------------------------------- */
.record-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3) var(--space-5);
  margin-bottom: var(--space-5);
}

.record-meta__stats {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2) var(--space-5);
}

.record-stat { font-size: 14px; color: var(--gray-700); }

.record-stat strong {
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 700;
  color: var(--gray-900);
  margin-right: 4px;
}

/* --- 4. "Is this you?" claim banner ----------------------------------------
   Replaces two separate bare yellow buttons ("This Competitor Is Me" and
   "I am {name} and I would like to create a login!"). Both express the same
   intent — this record is, or should be, mine — and differ only by whether
   the viewer has a login. One component, two copy variants.

   Full-width and wrapping, so it cannot be clipped by the badge the way a
   fixed-width inline button is.                                             */
.claim-banner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 var(--space-5) 0;
  background: #fdf8ea;
  border: 1px solid #f0dfae;
  border-left: 4px solid var(--nastar-gold);
  border-radius: var(--radius);
}

.claim-banner__icon {
  flex: 0 0 auto;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--nastar-gold);
  color: var(--gray-900);
  font-size: 17px;
  font-weight: 700;
  font-family: var(--font-heading);
  display: flex;
  align-items: center;
  justify-content: center;
}

.claim-banner__text { flex: 1 1 300px; min-width: 0; }

.claim-banner__title {
  display: block;
  font-family: var(--font-heading);
  font-size: 17px;
  font-weight: 700;
  color: var(--gray-900);
  margin-bottom: 2px;
}

.claim-banner__body { font-size: 14px; line-height: 1.45; color: var(--gray-700); }

.claim-banner__action { flex: 0 0 auto; }
.claim-banner__action form { margin: 0; }
.claim-banner__action .btn { font-size: 14px; }

/* --- 6. Narrow screens ------------------------------------------------------
   Below 992px the badge is display:none, so the collision is gone, but the
   action still must not sit beside the name. Stacking is the default here
   because the header is flex-wrap, so this only tightens type sizes.        */
@media (max-width: 600px) {
  .record-header__name { font-size: 27px; }
  .record-header__actions { width: 100%; }
  .record-header__actions .btn { width: 100%; }

  /* --- Vertical budget on a phone ------------------------------------------
     Measured at 390x844 before this block: the racer's own content began 571px
     down on their own record and 758px down on someone else's -- 90% of the
     screen. The claim banner alone was 245px: icon 28, three lines of body copy
     115, a full-width button 44, plus padding.

     The explanation does not need to live here. Clicking through lands on
     compmergerequest.jsp, which shows both records, explains the merge and asks
     for confirmation. The banner's job is to raise the question, not answer it,
     so the body copy is now one short line and the button sits inline.

     Note the ceiling: the tab strip below is 114px (8 tabs over 3 rows) and is
     off-limits, so it is the largest single block on the page regardless. */
  /* Single row on a phone: the question and the action, nothing else. The
     body copy is suppressed rather than shortened -- on this width every extra
     line costs more than it explains, and compmergerequest.jsp (or the
     quick-registration page) gives the full explanation on arrival. The button
     label carries the meaning: "This is me" / "Create your login". */
  .claim-banner {
    flex-wrap: nowrap;
    align-items: center;
    padding: var(--space-2) var(--space-3);
    gap: var(--space-3);
  }
  .claim-banner__icon { display: none; }
  .claim-banner__body { display: none; }
  .claim-banner__text { flex: 1 1 auto; min-width: 0; }
  .claim-banner__title { font-size: 16px; margin-bottom: 0; }
  .claim-banner__action { width: auto; flex: 0 0 auto; }
  .claim-banner__action .btn { width: auto; font-size: 13px; padding: 0 var(--space-3); }

  .record-header { gap: var(--space-2) var(--space-4); padding-bottom: var(--space-2); margin-bottom: var(--space-3); }
  .record-meta { gap: var(--space-2) var(--space-4); margin-bottom: var(--space-3); }
  .record-meta__stats { gap: var(--space-1) var(--space-4); }
}

/* --- 7. Online race registration nudge -------------------------------------
   Replaces the inline "Enter a Race" link, which measured 99.8x16px: italic,
   14px (the legacy `* { font-size:14px }` rule shrinks it inside its own 28px
   bold heading), default link colour, no weight, no icon, sitting after fifteen
   &nbsp; entities. Smallest text on the biggest line, with nothing marking it
   as an action.

   Placed in the header action slot, which keeps two properties of the original:
   it stays above the tab strip, so it is visible on every tab (TOOLS is in
   comp2Personal.jsp and therefore PERSONAL-only), and it costs no vertical
   space above the racer's own results.

   Gold because on this page gold already means "actionable" -- the TOOLS box
   and the active tab both use it -- while navy means "navigate". The old link
   spoke neither language.

   The label carries the count rather than naming an abstraction, and the whole
   control is omitted when the count is zero, so it is never a dead end. It
   points at ?pagename=register, not ?pagename=EnterARace: the two run the same
   query, but register.jsp sorts correctly by `start` where enterARace.jsp sorts
   by the formatted date *string*.                                            */

.record-nudge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: var(--tap-min);
  padding: 0 var(--space-4);
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  background: var(--nastar-gold);
  color: var(--gray-900);
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none !important;
  cursor: pointer;
  max-width: 320px;
}
.record-nudge:hover { background: var(--nastar-gold-dark); color: #fff; }

/* The count flows inline as part of the sentence rather than sitting as a
   separate display-sized element. Emphasis is weight only, no size jump, so
   the control reads as one line of text and wraps naturally. */
.record-nudge__label { font-weight: 600; }
.record-nudge__label b { font-weight: 700; }

.record-nudge__arrow { margin-left: auto; font-size: 15px; }

@media (max-width: 600px) {
  .record-nudge { width: 100%; max-width: none; justify-content: flex-start; }
}


/* --- 8. Season picker promoted into the stats row --------------------------
   Previously the season control sat at the far right of the meta row under
   `justify-content: space-between`, which at 1440px put it ~700px from the
   stats it modifies -- the corner of the page that gets looked at least, for
   what is probably the most-used control on a racer's own record.

   Here the season *is* the control: the thing you read is the thing you
   change, so "Change to:" and the separate Go button are no longer needed.
   The select already carries onchange="jumpPage(...)", so it navigates on
   selection; Go was only a no-JS fallback, and comp2's tab content already
   requires JS to render at all.

   Implementing this for real means three small changes in
   comp2Global.jsp's listLinksForOtherYears(): stop emitting the "Change to: "
   text, drop the "Select a Year" placeholder, and mark the current season
   `selected` so the control shows the season being viewed.               */

.record-meta { justify-content: flex-start; }

.record-season {
  display: flex;
  align-items: baseline;
  flex: 0 0 auto;
}
.record-season form { display: flex; align-items: center; margin: 0; }
.record-season select {
  font-family: var(--font-heading) !important;
  font-size: 19px !important;
  font-weight: 700;
  color: var(--gray-900);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  padding: 2px 4px 2px 6px;
  margin: 0;
  cursor: pointer;
  max-width: 260px;
}
.record-season select:hover { border-color: var(--gray-300); background: var(--gray-100); }
.record-season select:focus { outline: 2px solid var(--nastar-blue); outline-offset: 1px; }

/* Gold, because on this site yellow simply means "button". Every submit on
   e.g. the rankings page is legacy `input.buttons` at #ffd203 with black text,
   including a "Go" directly analogous to this one. An outline button here was
   the only one of its kind on the site and did not read as a button at all.

   --nastar-gold (#eaaf1d) rather than the legacy #ffd203: same intent, and the
   theme deliberately tightened that accent for contrast. Hierarchy against the
   registration nudge comes from size and placement -- this is a small utility
   control beside a select, that is a large one in the action slot -- not from
   being the only gold element.

   The Go button stays. It is the no-JS fallback -- the form posts properly
   without it -- and, more importantly, the only thing that could ever make the
   control usable from the keyboard: `onchange` navigates on every arrow press
   while the select is closed, so a keyboard user cannot reach an option further
   down the list. That is pre-existing and out of scope here, but removing Go
   would foreclose the fix. Legacy `input.buttons` hard-codes height:22px and
   line-height:22px, which clips the label once padding is added, so both reset. */
.record-season input[type="submit"] {
  font-size: 13px;
  font-weight: 700;
  height: auto;
  line-height: 1;
  margin: 0 0 0 var(--space-2);
  text-transform: none;
  padding: 9px 16px;
  border: 0;
  border-radius: var(--radius-sm);
  background: var(--nastar-gold);
  color: var(--gray-900);
  cursor: pointer;
}
.record-season input[type="submit"]:hover {
  background: var(--nastar-gold-dark);
  color: var(--white);
}

/* --- 9. Nudge sizing on small screens --------------------------------------
   The earlier rule forced width:100% on phones, producing a full-width
   two-line gold block ~52px tall that outweighed the racer's own name. The
   button now sizes to its content and drops to a shorter label.            */

@media (max-width: 600px) {
  /* Full label kept -- it is what makes the control self-explaining, which is
     the entire point of the nudge. Sized down and allowed to wrap to two lines.

     Two lines is deliberate. Measured at 390px: the label needs 281px on one
     line, plus 20px padding, a 13px arrow and an 8px gap = 322px against a
     319px slot. Fitting it on one line requires dropping to 12px type, which
     leaves about 1px of slack and breaks as soon as the count reaches two
     digits. The sentence is simply longer than a phone is wide. */
  .record-nudge {
    width: auto;
    max-width: 100%;
    /* Back to the 44px tap minimum. The shorter label fits on one line here,
       so the height is spent on the touch target rather than on wrapped text. */
    min-height: var(--tap-min);
    padding: 8px var(--space-3);
    font-size: 13px;
    line-height: 1.3;
    align-items: center;
  }
  .record-nudge__arrow { margin-left: var(--space-2); }
}


/* --- 10. Touch targets on phones -------------------------------------------
   Measured on the live record page at 390px: the season <select> renders 18px
   tall and its Go button 22px, against a 44px minimum. The select is the most
   used control on a racer's own record, so it is the one that matters most.
   Sized up only below the desktop breakpoint; the desktop treatment is
   deliberately typographic and does not want a 44px box.                    */
@media (max-width: 991px) {
  .record-season input[type="submit"] { min-height: var(--tap-min); padding: 0 16px; }
  .record-season select {
    min-height: var(--tap-min);
    padding: 6px 8px;
    border-color: var(--gray-300);
    background: var(--white);
  }
}


/* --- 11. Claim prompt: banner on desktop, inline link on phones ------------
   The banner costs 85px of vertical space on a 390px phone, which pushed the
   racer's own results further down the screen -- against the whole point of
   the page. On a phone the prompt collapses to a text link hung off the
   registration-number line, which is short and half empty, so it costs nothing.

   It is on the line *below* the name deliberately: 20,604 records have names
   long enough to run into trouble beside a control at 34px, and this sidesteps
   that entirely because the line's width is set by the registration number.

   The banner survives at >=992px, where there is room and it was approved. */

/* `.main-container a { text-decoration: underline }` (nastar.css:1288, the
   "restore underlines on legacy content links" rule) out-specifies a bare
   .record-claim, so this needs the element selector to win. Buttons should not
   be underlined; content links still should. Same applies to .record-nudge. */
a.record-claim,
a.record-nudge { text-decoration: none; letter-spacing: 0; text-transform: none; }
a.record-claim:hover,
a.record-nudge:hover { text-decoration: none; }
/* A compact gold button on its own line, not a text link.

   A link blends into the page and does not read as an available action, which
   is exactly why the legacy design used gold buttons in the first place -- on
   this page gold means actionable. The claim prompt is the one thing here we
   most want a racer to notice, so it should not be the quietest element.

   First person, and it states the outcome: the button this replaces ("I am
   {name} and I would like to create a login!") got both of those right even
   though it was 399px wide and clipped by the logo.

   Sized to content and allowed to wrap, at the 44px tap minimum. The identity
   block is 230px wide on a 390px phone, so a two-line wrap is expected. */
.record-claim {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 6px var(--space-3);
  border-radius: var(--radius-sm);
  background: var(--nastar-gold);
  color: var(--gray-900);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.25;
  white-space: normal;
}
.record-claim:hover { background: var(--nastar-gold-dark); color: #fff; text-decoration: none; }
.record-claim:hover { text-decoration: underline; }

@media (min-width: 992px) {
  .record-claim { display: none; }
}
@media (max-width: 991px) {
  .claim-banner { display: none; }
}

@media (max-width: 991px) {
  /* Share the registration-number line rather than taking a row of its own.
     That line is only ~20px of text, so absorbing a 44px button costs 23px
     rather than 51px, and the tap target stays finger-sized.

     The label has to stay short. Measured at 390px against the *longest*
     registration number in comptable (SCH14199 -> "NASTAR #SCH14199", 149px)
     on a 319px line, leaving 158px for the button:

         "This is me"             114px  fits for 100% of racers
         "This Racer is me"       160px  wraps for the 34.2% whose
                                         registration number is 7-8 chars
         "This Competitor is me"  201px  wraps for most

     A third of racers getting a different layout is worse than either
     consistent option, so the label stays short and the outcome is stated on
     the page the button leads to. Dropping the "NASTAR" prefix would buy the
     room, but that label has to stay. */
  .record-header__id {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
  }
}

/* -----------------------------------------------------------------------
   Registration visual modernization (2026-08-21) -- CSS-only, first pass.

   Scoped entirely under .reg-modern, a class added to the single
   <table> includes/register.jsp opens (the one line-12 attribute is the
   only markup change on this page). Empirically confirmed via a real
   browser that every field in the logged-out registration form --
   including the honeypot's neighbours and the submit button -- is a
   genuine DOM descendant of that table, so this scope is reliable.

   Nothing here touches .form-field unscoped, nastar_2019.css, or
   editcomp.jsp, so quickregistration.jsp and the Aspen/SMS walk-up claim
   page (doc/venue-registration-sms-flow.md) are unaffected -- they don't
   carry this class and these rules don't match anything on that page.

   Edit Profile (comp.jsp, page=comp1&editcomp=Yes) was investigated for
   the same treatment and deliberately skipped: a test wrapper div placed
   around that form was NOT contained by it in the rendered DOM (the
   surrounding table markup there has a pre-existing nesting imbalance
   that predates this work), so no reliable scoping hook exists without
   restructuring markup this task must not touch. See the chat report for
   detail; that page is unchanged.
   ----------------------------------------------------------------------- */

.reg-modern {
  width: 100%;
  max-width: 640px;
  margin: var(--space-5, 24px) auto;
  border-collapse: separate;
  font-family: var(--font-body, 'Roboto', sans-serif);
}

.reg-modern .register-section-heading {
  font-family: var(--font-heading, 'Roboto Condensed', sans-serif);
  font-size: 20px;
  font-weight: 700;
  color: var(--nastar-blue-dark, #1b417d);
  margin-top: var(--space-5, 24px);
}

.reg-modern .register-section-heading-right {
  font-size: 13px;
  color: var(--gray-500, #6f7378);
}

.reg-modern #dottedline {
  border-bottom: 1px solid var(--gray-200, #e2e5e9);
  margin: 6px 0 var(--space-4, 16px);
}

/* Each labeled field. Overrides nastar_2019.css's float-based two-column
   layout (label float:left, fixed 200px width) with a simple stacked
   block -- label above control. This is what actually fixes the mobile
   wrapping seen in the current layout (the birthdate month/day/year row
   in particular): no breakpoint-specific column collapse logic is needed
   because there are no columns to collapse. Same rule applies at every
   width, which is what "one responsive design" means here. */
.reg-modern .form-field {
  display: block;
  clear: both;
  margin-bottom: var(--space-4, 16px);
}

.reg-modern .form-field label {
  display: block;
  float: none;
  width: auto;
  text-align: left;
  padding-right: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--gray-700, #46484c);
  margin-bottom: 6px;
}

/* NOT display:flex. The birthdate field mixes plain text ("Month:",
   "Day:", "Year:") with three <select> elements in one <value>; flex
   turns that text into anonymous flex items that wrap independently of
   the selects, scrambling the Month/Day/Year order. Plain block flow
   keeps text and each select together exactly as the markup orders
   them, which is what makes this safe to do with zero HTML changes. */
.reg-modern .form-field value {
  display: block;
  padding-left: 0;
  line-height: 2.4;
}

.reg-modern .form-field-note {
  display: block;
  padding-left: 0;
  font-size: 12px;
  color: var(--gray-500, #6f7378);
  margin-top: 4px;
}

.reg-modern .error-message-small {
  color: #d0142c;
  font-size: 12px;
}

/* Text/password inputs and selects. Fixed width from the deprecated
   size="" attribute is overridden so nothing can force horizontal
   overflow at phone widths; box-sizing keeps padding from adding to that
   width. min-height keeps touch targets comfortable on an iPhone (the
   walk-up-registration device, per the venue-flow doc) without changing
   any input's type/name/value. */
.reg-modern input.input-text,
.reg-modern input[type="password"],
.reg-modern select.pulldown-menu {
  width: 100%;
  max-width: 360px;
  box-sizing: border-box;
  min-height: 44px;
  padding: 8px 12px;
  font-size: 15px;
  border: 1px solid var(--gray-300, #c7cbd1);
  border-radius: var(--radius, 8px);
  background: #fff;
}

.reg-modern input.input-text:focus,
.reg-modern input[type="password"]:focus,
.reg-modern select.pulldown-menu:focus {
  outline: 2px solid var(--nastar-blue, #2f6fae);
  outline-offset: 1px;
  border-color: var(--nastar-blue, #2f6fae);
}

/* Middle Initial (editcomp.jsp:70) is maxlength=1 -- one character.
   The general rule above sets width:100% so ordinary fields fill their
   row, but that same width:100% ignores this field's legacy size="2"
   hint and stretches it exactly as wide as First/Last Name, even though
   it can never hold more than one letter. Fixed at every tier (not just
   desktop) since the general rule's width:100% applies everywhere.
   The extra [name="mname"] attribute selector, not another class, is
   what makes this beat the general rule on specificity regardless of
   media-query/source order, so it doesn't matter where in the cascade
   it sits. */
.reg-modern input.input-text[name="mname"] {
  width: 70px;
  max-width: 70px;
  flex: 0 0 auto;
}

/* Birthdate is the one field with three <select>s sharing a single
   <value> next to plain "Month:"/"Day:"/"Year:" text (see the value
   display:block comment above). Content-sized widths instead of the
   100%/360px used everywhere else let them sit inline with that text
   instead of each trying to stretch to 360px on its own line. IDs
   (rather than another class) keep this change to CSS only. */
.reg-modern select#birthdatem,
.reg-modern select#birthdated,
.reg-modern select#birthdatey {
  display: inline-block;
  width: auto;
  max-width: none;
  min-height: 40px;
  margin: 4px 2px 10px 4px;
  vertical-align: middle;
}

/* Gender radios and the hide-hometown / waiver checkboxes: bigger,
   easier to tap, with breathing room from the label text next to them. */
.reg-modern input[type="radio"],
.reg-modern input[type="checkbox"] {
  width: 24px;
  height: 24px;
  margin-right: 6px;
  vertical-align: middle;
}

/* Waiver text (existing readonly <textarea>, unchanged) and its "I
   agree" checkbox row. */
.reg-modern textarea.form-control {
  width: 100%;
  max-width: 100%;
  min-height: 160px;
  box-sizing: border-box;
  border: 1px solid var(--gray-300, #c7cbd1);
  border-radius: var(--radius, 8px);
  padding: 12px;
  font-size: 13px;
  line-height: 1.5;
  background: var(--gray-100, #f4f6f8);
}

/* The existing inline-styled error box (bgcolor="#ffd203" table with no
   class, emitted only when $errormessage is non-empty). Attribute
   selector so no markup change is needed to reach it. */
.reg-modern table[bgcolor="#ffd203"] {
  width: 100%;
  border: 1px solid #eaaf1d !important;
  border-radius: var(--radius, 8px);
  background: #fff8e6 !important;
}

.reg-modern table[bgcolor="#ffd203"] td {
  padding: 14px !important;
}

/* Register / Update submit button. nastar_2019.css:611-618 sets
   input.buttonsNoCase to a fixed height:22px and line-height:22px. Since
   height and min-height are different properties, setting only
   min-height here (as this rule originally did) left that fixed
   height:22px still in force -- with box-sizing:border-box, the larger
   padding below then ate into that fixed 22px box instead of growing
   it, clipping the button. height/line-height must be explicitly
   overridden here, not just padding/min-height. */
.reg-modern input.buttonsNoCase {
  display: inline-block;
  background: var(--nastar-gold, #eaaf1d);
  border: none;
  border-radius: var(--radius, 8px);
  padding: 12px 32px;
  font-size: 15px;
  font-weight: 700;
  color: #3a2a00;
  cursor: pointer;
  height: auto;
  line-height: normal;
  min-height: 44px;
}

.reg-modern input.buttonsNoCase:hover {
  background: var(--nastar-gold-dark, #a8760a);
  color: #fff;
}

/* Tablet/phone: the form already stacks by default (no column layout to
   collapse), so this is fine-tuning rather than a structural change --
   tighter outer margins and slightly smaller type so the card doesn't
   feel like it is fighting the viewport edge. */
@media (max-width: 700px) {
  .reg-modern {
    margin: var(--space-4, 16px) auto;
  }

  .reg-modern .register-section-heading {
    font-size: 18px;
  }

  .reg-modern input.input-text,
  .reg-modern input[type="password"],
  .reg-modern select.pulldown-menu {
    max-width: 100%;
    font-size: 16px; /* >=16px avoids iOS Safari auto-zoom on focus */
  }
}

/* Tablet tier (701-899px), added 2026-08-22. Sits between the phone
   rules above and the row-layout desktop rules below. Layout stays
   stacked -- deliberately not switching to the row layout here, to
   avoid re-verifying the birthdate/note flex interaction at a third
   breakpoint. This is a sizing-only tier.
   Two things this tier exists to fix, not just density:
   1) Below 900px there was no rule for 701-899px at all, so it fell
      through to the base (desktop-oriented) input font-size of 15px --
      one pixel under the 16px iOS/iPadOS Safari zoom-on-focus threshold.
      768px is iPad-portrait width, so that gap was a real bug, not just
      a density mismatch. font-size:16px below is what closes it.
   2) The un-tiered jump from this range straight to the >=900px row
      layout measured at 885px (41%) of total form height for a 1px
      change in viewport width. This tier halves that step.
   The birthdate selects need no override here: their own min-height
   (set by ID, above) is already 40px at every width up to the 900px
   desktop query, which happens to match this tier's control height. */
@media (min-width: 701px) and (max-width: 899px) {
  .reg-modern input.input-text,
  .reg-modern input[type="password"],
  .reg-modern select.pulldown-menu {
    min-height: 40px;
    padding: 6px 10px;
    font-size: 16px; /* >=16px avoids iOS/iPadOS Safari auto-zoom on focus */
  }

  .reg-modern .form-field {
    margin-bottom: 12px;
  }
}

/* Desktop only, well clear of the 768px tablet width so that layout is
   untouched: label and control side by side instead of stacked, to claw
   back the vertical density the all-widths stacked layout gave up. This
   only changes how .form-field's two existing children (label, value)
   are arranged relative to each other -- no new markup, and the
   birthdate field's <value> stays display:block exactly as set above
   (that fix is about its mixed text/select content, not about row vs.
   column direction, so it is unaffected by and still needed here). */
@media (min-width: 900px) {
  .reg-modern {
    max-width: 720px;
  }

  .reg-modern .form-field {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
  }

  .reg-modern .form-field label {
    flex: 0 0 170px;
    width: 170px;
    text-align: right;
    margin-bottom: 0;
  }

  .reg-modern .form-field value {
    flex: 1 1 auto;
    min-width: 0;
  }

  /* The note (editcomp.jsp:336) is its OWN .form-field with an empty
     <label></label> -- not a second child inside birthdate's field. The
     row-flex rule above already reserves the same 170px label column for
     that empty label, so the note's value naturally lines up under
     birthdate's control with zero extra margin. The stacked-layout
     margin-left from the base rule above must be cancelled here, or it
     doubles up with the flex offset and the note shoots off to the
     right of the row entirely. */
  .reg-modern .form-field-note {
    margin-left: 0;
    margin-top: 0;
  }

  /* Density pass (2026-08-22). Measured against the pre-redesign
     desktop form by toggling .reg-modern off/on in a live browser at
     1280px: the dominant cost was NOT the row-flex layout above, it was
     controls sized for touch (44px min-height, 8px padding) carried
     over unchanged from the mobile-first rules earlier in this file.
     A mouse pointer does not need a 44px target, so these three rules
     scale that down for desktop only -- 390px/768px are untouched,
     since neither is affected by a min-width:900px query. */
  .reg-modern input.input-text,
  .reg-modern input[type="password"],
  .reg-modern select.pulldown-menu {
    min-height: 34px;
    padding: 5px 10px;
    font-size: 14px;
  }

  .reg-modern textarea.form-control {
    /* Trimmed less aggressively than the controls above on purpose --
       this is a liability waiver, not a text field, and legibility of
       its content matters more than reclaiming a few more pixels. */
    min-height: 115px;
  }

  .reg-modern input.buttonsNoCase {
    min-height: auto;
    padding: 9px 26px;
  }

  .reg-modern .register-section-heading {
    margin-top: 16px;
  }

  /* Keep the birthdate selects (sized separately above, by ID, to fix
     the Month/Day/Year wrapping bug) visually consistent with the
     smaller general control height set just above, rather than looking
     oversized next to it. */
  .reg-modern select#birthdatem,
  .reg-modern select#birthdated,
  .reg-modern select#birthdatey {
    min-height: 32px;
  }
}


/* ===========================================================================
   Login page (includes/login.jsp)

   Reached by pagename=login (and the /user rewrite), pagename=home, and
   index.jsp's catch-all -- so these rules style every unrecognized URL on the
   site as well. That is existing routing and is not changed here.

   px throughout, not rem: legacy nastar_2019.css carries `* { font-size:14px }`
   as a direct rule on every element, so it lands on <html> too and rem cannot
   express sizes that match nastar.com. Same reason as the record-header block
   above. Tokens (--nastar-*, --gray-*, --space-*, --tap-min) come from
   theme_2026/css/nastar.css.

   Nothing here touches shared chrome. The footer-width defect on this page was
   a dangling `<!--` at the end of includes/login.jsp, not CSS -- see
   doc/skiracing-open-issues.md item 24.
   =========================================================================== */

.login-page {
  max-width: 560px;
  margin: var(--space-5) auto var(--space-8);
  text-align: left;
}

.login-card {
  background: var(--white);
  border: 1px solid var(--gray-200);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--space-5);
}

/* --- Fields ---------------------------------------------------------------
   `* { font-size: 14px }` in nastar_2019.css is a direct rule on the input, so
   a class selector is enough to beat it. 16px on the control itself is not a
   style preference: iOS Safari (and the Flutter WebView on iOS) zooms the page
   when a focused input is under 16px. */

.login-field { margin: 0 0 var(--space-4); }

.login-field label {
  display: block;
  margin: 0 0 var(--space-1);
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--gray-700);
}

.login-page input.login-input {
  display: block;
  width: 100%;
  min-height: var(--tap-min);
  padding: 0 var(--space-3);
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--gray-900);
  background: var(--white);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius-sm);
}

.login-page input.login-input:focus {
  outline: 2px solid var(--nastar-blue);
  outline-offset: 1px;
  border-color: var(--nastar-blue);
}

/* --- Buttons --------------------------------------------------------------
   .btn already carries min-height:var(--tap-min) and
   `text-decoration:none !important`, so the anchor variant is safe against
   nastar.css:1288's `.main-container a { text-decoration: underline }`.
   Only the font-size needs restating, for the 14px-root reason above. */

.login-page .btn.login-btn {
  font-size: 15px;
  font-weight: 700;
}

.login-page input.login-btn--submit {
  display: block;
  width: 100%;
  margin-top: var(--space-2);
  -webkit-appearance: none;
  appearance: none;
}

/* --- Notices (error / recovery result) ------------------------------------ */

.login-notice {
  margin: 0 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-sm);
  border-left: 4px solid var(--gray-300);
  background: var(--gray-100);
  font-size: 14px;
  line-height: 1.5;
  color: var(--gray-900);
}

.login-notice--error {
  border-left-color: #ed2e43;
  background: #fdecee;
}

.login-notice--warn {
  border-left-color: var(--nastar-gold);
  background: #fdf6e3;
}

.login-notice--ok {
  border-left-color: var(--nastar-blue);
  background: #eef4fa;
}

.login-notice__detail {
  display: block;
  margin-top: var(--space-1);
  font-size: 13px;
  color: var(--gray-700);
}

/* --- Recovery disclosure --------------------------------------------------
   Kept on the page rather than moved off it: it is the second-most-used
   action here, and the previous design had it permanently expanded below ~250
   pixels of <br>. A <details> keeps it one tap away without competing with
   the primary Log In button. */

.login-recovery {
  margin-top: var(--space-5);
  padding-top: var(--space-4);
  border-top: 1px solid var(--gray-200);
}

.login-recovery__summary {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  cursor: pointer;
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: 700;
  color: var(--nastar-blue);
  list-style: none;
}

.login-recovery__summary::-webkit-details-marker { display: none; }

.login-recovery__summary::before {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-right: var(--space-3);
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(-45deg);
  transition: transform 0.15s ease;
}

.login-recovery[open] > .login-recovery__summary::before {
  transform: rotate(45deg);
}

.login-recovery__summary:focus-visible {
  outline: 2px solid var(--nastar-blue);
  outline-offset: 2px;
}

.login-recovery__body { padding-top: var(--space-2); }

.login-recovery__lead {
  margin: 0 0 var(--space-4);
  font-size: 14px;
  line-height: 1.5;
  color: var(--gray-700);
}

.login-page input.login-btn--recovery {
  display: block;
  width: 100%;
  -webkit-appearance: none;
  appearance: none;
}

.login-recovery__help {
  margin: var(--space-4) 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--gray-700);
}

/* --- Create-account block -------------------------------------------------
   Visually separated from the card on purpose: it is a different task, not a
   third option inside the login form. The wording avoids "Register", which on
   this site already means online race registration (open-issues item 9). */

.login-newaccount {
  margin-top: var(--space-5);
  padding: var(--space-5);
  border: 1px dashed var(--gray-300);
  border-radius: var(--radius);
  background: var(--gray-100);
  text-align: center;
}

.login-newaccount__lead {
  margin: 0 0 var(--space-2);
  font-family: var(--font-heading);
  font-size: 18px;
  font-weight: 700;
  color: var(--gray-900);
}

.login-newaccount__note {
  margin: 0 0 var(--space-4);
  font-size: 13px;
  line-height: 1.5;
  color: var(--gray-700);
}

.login-newaccount__btn { display: inline-flex; }

/* --- Signed-in state ------------------------------------------------------
   Replaces 31 consecutive <br> tags. */

.login-card--signedin { text-align: center; }

.login-signedin__welcome {
  margin: 0 0 var(--space-1);
  font-family: var(--font-heading);
  font-size: 22px;
  font-weight: 700;
  color: var(--gray-900);
}

.login-signedin__sub {
  margin: 0 0 var(--space-5);
  font-size: 14px;
  color: var(--gray-700);
}

.login-card--signedin .login-btn { display: inline-flex; }

.login-signedin__note {
  margin: var(--space-5) 0 0;
  font-size: 13px;
  color: var(--gray-500);
}

.login-footnote {
  margin: var(--space-5) 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--gray-500);
  text-align: center;
}

/* --- Phones ---------------------------------------------------------------
   The card loses its side inset so the controls keep their full width on a
   390px screen, and the create-account button goes full width to stay a
   comfortable target. */

@media (max-width: 600px) {
  .login-page {
    margin-top: var(--space-4);
    margin-bottom: var(--space-6);
  }

  .login-card,
  .login-newaccount {
    padding: var(--space-4);
  }

  .login-newaccount__btn {
    display: flex;
    width: 100%;
  }
}

/* --- Mobile-band logo: centered on the physical viewport ------------------
   Approved 2026-08-23 (Katie's suggestion, reviewed by David on DEV at
   390/430/800/1440px). nastar.css's default
   (.site-header__band-inner { justify-content: space-between }) centers
   nothing -- it just puts the logo at the left edge and the hamburger at the
   right. This override takes the logo out of flex flow so it can be
   centered independently; the hamburger stays the only flex item, still
   pinned right by the same justify-content:flex-end used at >=992px
   elsewhere in nastar.css.

   `left: 50vw`, not `left: 50%`: this site and nastar.com reserve a
   scrollbar gutter (nastar.css) but at slightly different document widths,
   so `50%` -- resolved against .site-header__band-inner's own box, which
   starts flush at the viewport's left edge -- centered the logo within each
   site's differing content box and produced a visible 4px shift crossing
   between the two. `vw` is a viewport-relative unit even on an absolutely
   positioned element, so `left: 50vw` places the logo at the *physical*
   viewport midpoint on both sites identically, regardless of any gutter
   reservation. Paired with `transform: translate(-50%, -50%)`, the logo's
   own center lands exactly on that midpoint.

   Scoped to skiracing-local.css, not nastar.css: this is this site's own
   override of the shared band-inner default, not a shared-chrome file
   change. nastar.com carries the corresponding change on its side.
   Boundary matches nastar.css's own `min-width: 768px` tablet breakpoint
   exactly. */
@media (max-width: 767px) {
  .site-header__band-inner {
    position: relative;
    justify-content: flex-end;
  }
  .site-logo--mobile {
    position: absolute;
    left: 50vw;
    top: 50%;
    transform: translate(-50%, -50%);
  }
}

/* --- Team-search autocomplete widget --------------------------------------
   Originally shipped inline in includes/checkresults.jsp for
   ?pagename=searchteam (2026-08-23/24, doc/skiracing-open-issues.md item 23).
   Extracted here (2026-08-24) so includes/teamracing.jsp (/team,
   /index.jsp/team) and checkresults.jsp's own checkresults/checkresults_2017
   branches can share one CSS copy instead of each carrying an independent
   one. Paired JS lives in theme_2026/js/skiracing-local.js. */
.team-search-row { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 8px; margin-bottom: 6px; }
.team-search-label { flex: 0 0 140px; max-width: 140px; box-sizing: border-box; text-align: right; padding-right: 8px; padding-top: 9px; font-size: 13px; }
.team-search-controls { display: flex; align-items: flex-start; flex-wrap: wrap; gap: 8px; flex: 1 1 auto; min-width: 0; }
.team-search-go { flex: 0 0 auto; white-space: nowrap; margin: 0; }
.team-search-note { font-size: 12px; font-style: italic; padding-left: 148px; margin: 0 0 14px 0; box-sizing: border-box; }
@media (max-width: 480px) {
	.team-search-label { flex-basis: 100%; max-width: 100%; text-align: left; padding-right: 0; padding-top: 0; margin-bottom: 2px; }
	.team-search-note { padding-left: 0; }
}
.team-autocomplete { position: relative; flex: 1 1 220px; min-width: 140px; max-width: 320px; }
.team-autocomplete-input { font-size: 16px; width: 100%; max-width: 320px; box-sizing: border-box; padding: 8px; border: 1px solid #b7b7b7; background-color: #fff; }
.team-autocomplete-panel { display: none; position: absolute; top: 100%; left: 0; width: 100%; max-width: 320px; overflow-y: auto; background: #fff; border: 1px solid #999; box-shadow: 0 2px 6px rgba(0,0,0,0.25); z-index: 1000; box-sizing: border-box; }
.team-autocomplete-item { display: flex; align-items: center; min-height: 44px; box-sizing: border-box; padding: 0 12px; font-size: 14px; cursor: pointer; border-bottom: 1px solid #eee; }
.team-autocomplete-item:active { background: #dde8ff; }
.team-autocomplete-empty { padding: 10px 12px; font-size: 13px; color: #777; }
.team-autocomplete-count { padding: 8px 12px; font-size: 12px; color: #777; border-bottom: 1px solid #eee; }
.team-autocomplete-more { display: flex; align-items: center; min-height: 40px; box-sizing: border-box; padding: 0 12px; font-size: 13px; color: #06c; cursor: pointer; }
.team-autocomplete-more:active { background: #eef; }

/* --- Notifications tab (includes/comp2Notifications.jsp) -------------------
   nastar_2019.css's .notify-text-enabled/.notify-text-disabled (unchanged,
   original production styling -- verified via prod-curl.sh against the live
   nastar_2019.css, identical class rules at the same line numbers) is a
   solid-color green/red pill, still used below for the "Notify me about"
   category rows (New Results, New Badges, etc.) exactly as production shows
   them. Leave that table alone -- it already matches production.

   The 2026-08-28 delivery-method table (commit b820e73, not yet deployed)
   reused .notify-text-disabled for two things it was never meant for:
     1. Plain caption text under each option -- the racer's own email
        address, phone number, and "(U.S. and Canada only)" -- unconditionally
        rendered as a solid red pill regardless of which method is selected.
     2. The "Not selected" state of every inactive delivery row (normally 2 of
        3 at once). Production's old single-line "Notifications will be sent
        by X to Y" never had a status indicator here at all.
   Together with the category table's own up to 4 red pills, that put 6-8
   solid red blocks on the page simultaneously -- reported 2026-09-07 as "too
   much red emphasis". Fixed as a markup-class change only in
   comp2Notifications.jsp: captions now use .notif-caption (neutral) and
   "Not selected" uses .notif-status-muted instead of .notify-text-disabled.
   Nothing here touches .notify-text-enabled/-disabled themselves or the
   category table, so production's look for that table is unaffected.

   .notif-status-muted is deliberately NOT a filled pill. Only the one
   affirmative state ("Selected", the legacy green .notify-text-enabled) gets
   a solid badge; the two-or-three inactive rows are plain recessive text. A
   grey box per inactive row still reads as three more things demanding
   attention, which is the problem this change exists to fix, and -- measured
   at 390px and 1400px -- the label wraps to two lines inside the narrow
   status column, so a filled box also broke visibly across the wrap. Plain
   text wraps harmlessly. */
.notif-caption {
  color: var(--gray-700);
}

/* The email-address caption only.
   An email has no break opportunity anywhere in it, so "david@siliconpeak.com"
   set a hard 175px floor on column 1 -- enough to push the delivery table to
   366px inside a 350px #comp2Body and scroll the page sideways at 390px once
   the pills above stopped wrapping. Letting it break removes that floor and the
   table returns to 350px.

   `anywhere`, NOT `break-word`: the two behave identically in normal flow, but
   only `anywhere` contributes soft-wrap opportunities to the MIN-CONTENT size
   calculation, which is what table column sizing uses. `break-word` was
   measured here first and changed nothing -- the table stayed 366px.

   Deliberately a modifier on the email row rather than on .notif-caption
   itself. Applied to every caption it also broke the Text Message row
   mid-abbreviation ("(U." / "S. and Canada only)"), and nothing else needs it:
   the longest token in the other three captions is "Notifications" /
   "notifications." / "13035550199", all of which fit the column unaided. Those
   keep breaking at spaces, as before. Neither value breaks a word that already
   fits, so desktop is unchanged. */
.notif-caption--email {
  overflow-wrap: anywhere;
}
.notif-status-muted {
  color: var(--gray-500);
}
.notif-status-muted .notify-icon-muted {
  color: var(--gray-300);
}

/* Keep a status pill's icon and its label on one line.
   Font Awesome's .fa sets display:inline-block, and an inline-block boundary
   creates a break opportunity, so the `<i>` icon and the word after it break
   apart independently of the &nbsp; between them. Measured at 390px, the
   green "Selected" and the red "Disabled" pills each rendered as a solid
   coloured box with the tick/cross alone on the first line and the word on
   the second.

   SCOPED TO `table.stripes` DELIBERATELY -- do not lift this to a bare
   `.notify-text-disabled`. comp2Notifications.jsp:146 puts that same legacy
   class on a full sentence ("These choices are saved, and will be used again
   when you select a delivery method above."), printed BETWEEN the two tables
   and therefore not matched here. An unscoped nowrap would make that sentence
   one unbreakable line and force horizontal page overflow -- the opposite of
   what this fixes. These two classes are used nowhere else in live code
   (comp2Notifications.jsp only), so this reaches exactly the status pills.

   Safe against overflow: each pill's content is an icon plus one short word
   ("Selected" / "Enabled" / "Disabled"), so the only effect is to raise that
   column's min-content width by roughly 25px. The label and link columns
   still wrap freely, which is what absorbs it. Verified 320-1400px, no
   horizontal scroll. */
table.stripes .notify-text-enabled,
table.stripes .notify-text-disabled {
  white-space: nowrap;
}

/* --- Racer photo hover/popup preview ---------------------------------------
   Reuses the nastar.com homepage leaderboard's racer-photo hover/popup
   mechanism (theme/css/home.css's .racerpop rules; JS ported to
   theme_2026/js/racer-photo-preview.js) for the existing legacy camera-icon
   affordance on rankings (includes/viewrankings.jsp) and race-results
   (includes/raceresults.jsp) pages -- see includes/photodisplay.jsp's
   racerCamIcon(). The icon itself (`.fa-camera` inside `.title-detailn`) is
   untouched; only the popover it opens is new.

   Deliberately NOT reusing the homepage's .lb__cam sizing rules (44px flex
   box with a negative-margin hit-area trick): those assume a flex row
   layout. Here the icon sits in a narrow legacy <td> inside an HTML table,
   and forcing a 44px box there would widen the icon column and risk the
   table-layout regression this change must avoid. `.racer-cam` therefore
   only adds interaction affordance, not sizing.

   Tokens (--nastar-blue, --gray-*, --radius*, --shadow-lg, --white) come
   from theme_2026/css/nastar.css, already loaded on every page. */
.racer-cam { cursor: pointer; }
.racer-cam:focus-visible {
  outline: 2px solid var(--nastar-blue);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.racerpop {
  position: absolute;
  z-index: 1100;
  width: min(320px, calc(100vw - 16px));
  padding: var(--space-2);
  border: 1px solid var(--gray-300);
  border-radius: var(--radius);
  background: var(--white);
  box-shadow: var(--shadow-lg);
}
.racerpop[hidden] { display: none; }
.racerpop__img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 60vh;
  object-fit: contain;
  border-radius: var(--radius-sm);
  background: var(--gray-100);
}
.racerpop.is-loading .racerpop__img { min-height: 120px; }
.racerpop__cap {
  margin: var(--space-2) 0 0;
  font: 700 13px/1.2 var(--font-heading);
  color: var(--gray-700);
  text-align: center;
}
.racerpop__close {
  position: absolute;
  top: 0; right: 0;
  width: var(--tap-min); height: var(--tap-min);
  border: 0;
  background: none;
  color: var(--gray-700);
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}
@media (hover: hover) {
  /* The close control is for touch, where there is nothing to hover away to. */
  .racerpop__close { display: none; }
}
