/* Public trade-show deadline warnings: homepage ticker + once-a-day visitor popup.

   Deliberately NOT an emergency banner - the Owner ruled that out twice. Urgency is carried by a
   small coloured dot and a short phrase, not by colouring whole blocks red. A homepage that shouts
   at every visitor about a deadline affecting a handful of them is worse than one that states the
   facts calmly.

   From T-5 the treatment is allowed to be stronger (.is-emphatic), which the Owner asked for: text
   weight, urgency colour, and - approved 2026-09-18 - a slow opacity breathe on the dot and the
   countdown pill of the red-band entries only.

   The earlier version pulsed a BORDER, which sat directly under the hero video and competed with
   it. The breathe is deliberately a different thing: no glow, no border, no size change, nothing
   on the show name, and confined to the two small marks that carry urgency. Everything calmer than
   T-5 stays completely still, and reduced motion holds it at full opacity.

   Brand tokens, with literal fallbacks so the block stays legible if it is ever rendered outside
   the main stylesheet. */

/* ---- urgency colours -------------------------------------------------------------------
   As CLASSES, not inline styles. The site's CSP sets style-src to 'self' plus hashes, which
   cover <style> blocks but never a style ATTRIBUTE - so the original style="--c:#c0392b" was
   refused on every element, the dots and pills rendered grey, and the console filled with
   violations. These land in the stylesheet the policy already trusts.

   The values match DeadlineUrgency on the server, which remains the single authority for which
   band a deadline is in; this file only decides what each band looks like. */
.u-yellow  { --c: #c9922b; }
.u-orange  { --c: #d2691e; }
.u-strong  { --c: #b34700; }
.u-red     { --c: #c0392b; }
.u-expired { --c: #5b6b8c; }
/* Blue, not grey. The Owner asked for the strip to read blue or orange, and blue is what a
   deadline that is simply "upcoming" should look like - grey read as disabled. */
.u-none    { --c: #6F91FF; }

/* ---- section + ticker ------------------------------------------------------------------- */

/* A strip, not a section. The first version was a full-width padded block with its own heading
   and a visible list of every deadline; the Owner rejected it for breaking the homepage layout and
   asked for a single rolling line under the video instead. So there is no band background, no
   vertical padding to speak of, and nothing here changes the height of the page around it. */
.ts-deadlines { padding: 0; background: none;
  /* Centred in the black gap below the video, and moved WITHOUT touching the layout.
     Measured on the running page: the video ends at 1225px and the TRUST marquee starts at 1371px
     - 146px of empty black - with the 44px strip sitting at the very bottom of it, flush against
     the marquee. A negative margin lifted the strip but dragged TRUST and everything below it up
     by the same amount, which is not what was asked and costs layout shift. `position: relative`
     offsets the painted strip while it keeps its original space in the flow, so the rest of the
     homepage does not move at all. */
  position: relative; top: -51px;
}
.ts-deadlines[hidden] { display: none !important; }

/* A button, because clicking it opens the full panel - styled back down to bare text. No border,
   no background, no chrome: the Owner asked for the two rules I had added here to go, keeping the
   homepage's own marquee lines (the .trust block below) as the only horizontal rules in this area.

   It scrolls the way the rest of the homepage scrolls: a masked viewport with the track sliding
   continuously, pausing on hover, matching .marquee / .marquee-track. The earlier version
   cross-faded between items in place, which is not what the Owner meant by 滚动. */
.tsd-ticker {
  position: relative; display: flex; align-items: center; box-sizing: border-box;
  width: 100%; height: 44px; margin: 0; padding: 0;
  /* The two orange rules the Owner asked to keep. Always accent-coloured rather than only when a
     deadline is urgent: they are the frame of the strip, and a frame that changes colour with the
     data would make the homepage look different from one day to the next. */
  border-left: 0; border-right: 0;
  border-top: 1px solid var(--accent, #ff6b4a);
  border-bottom: 1px solid var(--accent, #ff6b4a);
  background: none; font: inherit; color: inherit;
  text-align: left; cursor: pointer; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
/* The name is the only part that looks clickable in its own right; the rest of the strip is a
   large, quiet target for "show me everything". */
.tsd-label { font: inherit; border: 0; background: none; padding: 0; color: inherit;
  font-weight: 600; white-space: nowrap; cursor: pointer; }
.tsd-label:hover, .tsd-label:focus-visible { text-decoration: underline; }
.tsd-label:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: 2px; }
.tsd-ticker { cursor: pointer; }
.tsd-ticker:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: 4px; }

/* The items are rendered twice and the track slides to -50%, so the loop repeats seamlessly.
   Full height with centred items, so the words sit exactly between the two rules rather than
   riding on the lower one. */
.tsd-track {
  display: flex; align-items: center; width: max-content; height: 100%; gap: 64px;
  animation: tsd-marquee 42s linear infinite;
}
.tsd-track .tsd-item { line-height: 1; }
.tsd-ticker:hover .tsd-track, .tsd-ticker:focus-visible .tsd-track { animation-play-state: paused; }
@keyframes tsd-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Every item stays in the DOM for assistive technology, laid out nowhere. */
.tsd-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

.tsd-item {
  display: flex; flex-wrap: nowrap; align-items: center; gap: 9px; flex: 0 0 auto;
  white-space: nowrap; text-decoration: none; font-size: .88rem;
  /* Coloured text, per the Owner: orange as a deadline gets close, blue while it is not urgent.
     The blue is #6F91FF - the one the homepage's own client marquee already uses - so the strip
     belongs to the page instead of introducing a second blue. */
  color: var(--c, #6F91FF);
}
a.tsd-item:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: -2px; }

.tsd-dot { flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%; background: var(--c, #6F91FF); }
.tsd-left {
  flex: 0 0 auto; padding: 1px 8px; border-radius: 999px; font-size: .72rem; font-weight: 700;
  letter-spacing: .03em; text-transform: uppercase; color: #fff; background: var(--c, #6F91FF);
}
.tsd-date { flex: 0 0 auto; color: var(--text-secondary, #5d6470);
  font-size: .8rem; font-variant-numeric: tabular-nums; }

/* Every item, always present, for reduced motion / no timers / screen readers. */
.tsd-all { list-style: none; margin: 0; padding: 0; }

/* From T-5 the strip is allowed to read louder. With the rules removed that is text weight alone;
   the urgency colour on the words and on the countdown pill carries the rest. */
.ts-deadlines.is-emphatic .tsd-label { font-weight: 700; }

/* ---- the breathing alert, Owner-approved 2026-09-18 -------------------------------------
   ONLY the entries that were already red-band: u-strong is T-5..T-3 and u-red is T-2..T-0.
   Everything calmer stays perfectly still, which is the point - a strip where every item moves
   signals nothing.

   OPACITY ONLY, and only on the dot and the countdown pill. Three things this deliberately is
   not:

     - not a glow. A coloured blurred shadow on this dark homepage is exactly the halo the design
       review bans, and it is the same thing that made the earlier pulsed border compete with the
       hero video directly above it.
     - not a transform or a size change. Those reflow a row that is already sliding horizontally,
       and the two motions fight each other.
     - not on the show name. The name has to stay readable while it scrolls past; fading the text
       somebody is trying to read is how an alert becomes an annoyance.

   3.2s is slow enough to read as breathing rather than flashing, and the fade never reaches zero,
   so the urgency marker stays visible at every point in the cycle. */
@keyframes tsd-breathe {
  0%, 100% { opacity: 1; }
  50%      { opacity: .45; }
}
.tsd-item.u-strong .tsd-dot,
.tsd-item.u-strong .tsd-left,
.tsd-item.u-red .tsd-dot,
.tsd-item.u-red .tsd-left {
  animation: tsd-breathe 3.2s ease-in-out infinite;
  /* The scrolling track already composites; keeping these on their own layer stops the fade from
     repainting the whole strip every frame. */
  will-change: opacity;
}

/* ---- the click-through panel -------------------------------------------------------------
   Every deadline, in the arrangement the homepage section used before it was cut back to a strip.
   It lives in a dialog now, which is where the Owner asked for it: visible on request, never
   occupying the homepage. */

.tsda-card { max-width: 620px; }
.tsda-note { margin: 0 0 14px; color: var(--text-secondary, #5d6470); font-size: .86rem; }

.tsda-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px;
  background: var(--border-subtle, #e3dcd5); border: 1px solid var(--border-subtle, #e3dcd5);
  border-radius: 10px; overflow: hidden; }
.tsda-list li { background: var(--bg-card, #fff); }

.tsda-row { display: flex; align-items: center; gap: 11px; padding: 12px 14px;
  text-decoration: none; color: inherit; }
a.tsda-row:hover, a.tsda-row:focus-visible { background: var(--bg-alt, #f6f3f0); }
a.tsda-row:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: -2px; }

.tsda-dot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 50%; background: var(--c, #6F91FF); }

/* Level one: a show name is a button, not a link - it opens the second level in place. */
.tsda-show-row { width: 100%; border: 0; background: none; font: inherit; cursor: pointer; }
.tsda-show-row:hover, .tsda-show-row:focus-visible { background: var(--bg-alt, #f6f3f0); }
.tsda-show-row:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: -2px; }
.tsda-go { margin-left: auto; font-size: 1.3rem; line-height: 1; color: var(--text-secondary, #5d6470); }

.tsda-back {
  display: inline-block; margin: 0 0 12px; padding: 6px 10px 6px 0; border: 0; background: none;
  font: inherit; font-size: .86rem; font-weight: 600; color: var(--accent, #ff6b4a); cursor: pointer;
}
.tsda-back:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: 2px; }

/* Level two: the evidence line. Every deadline carries the page or manual it was read from -
   a date with no visible provenance is indistinguishable from one we made up. */
.tsda-evidence { display: block; margin-top: 3px; font-size: .78rem; }
.tsda-src { color: var(--accent, #ff6b4a); text-decoration: underline; overflow-wrap: anywhere; }
.tsda-src-none { color: var(--text-secondary, #5d6470); text-decoration: none; font-style: italic; }
.tsda-checked { color: var(--text-secondary, #5d6470); }
.tsdp-evidence { margin-top: 8px; font-size: .78rem; }
.tsda-text { display: grid; gap: 2px; min-width: 0; }
.tsda-show { font-weight: 700; overflow-wrap: anywhere; }
.tsda-type { color: var(--text-secondary, #5d6470); font-size: .86rem; }
.tsda-when { margin-left: auto; display: grid; gap: 2px; justify-items: end; text-align: right; }
.tsda-left { font-size: .74rem; font-weight: 700; letter-spacing: .03em; text-transform: uppercase;
  color: var(--c, #6F91FF); white-space: nowrap; }
.tsda-date { color: var(--text-secondary, #5d6470); font-size: .8rem; white-space: nowrap;
  font-variant-numeric: tabular-nums; }

/* Below the width where a left gutter exists, there is nothing to sit in: the card goes back to
   filling the screen, because a left-anchored dialog on a phone is just a dialog with a wasted
   margin on one side. */
@media (max-width: 900px) {
  .tsdp-backdrop { justify-items: center; padding: 20px; }
}

@media (max-width: 480px) {
  .tsda-row { flex-wrap: wrap; }
  .tsda-when { margin-left: 19px; justify-items: start; text-align: left; }
}

/* ---- popup ------------------------------------------------------------------------------ */

/* Left, not centred. The Owner asked for the dialog to sit in the dark empty area down the left
   of the page rather than over the middle of the content - centred, it covered the very hero the
   visitor was looking at. Vertically it stays centred; only the horizontal anchor moves. */
.tsdp-backdrop {
  position: fixed; inset: 0; z-index: 9000; display: grid;
  align-items: center; justify-items: start;
  padding: 20px clamp(20px, 5vw, 64px); background: rgba(10, 12, 16, .55); overflow-y: auto;
}
.tsdp-card {
  position: relative; width: 100%; max-width: 440px;
  background: var(--bg-card, #fff); color: var(--text-primary, #16181d);
  border: 1px solid var(--border-subtle, #e3dcd5); border-radius: 14px;
  padding: 26px 24px 20px; box-shadow: 0 18px 50px rgba(10, 12, 16, .28);
}
.tsdp-card.is-emphatic { border-color: var(--accent, #ff6b4a); border-width: 2px; }

.tsdp-close {
  position: absolute; top: 8px; right: 10px; width: 34px; height: 34px;
  border: 0; background: transparent; color: var(--text-secondary, #5d6470);
  font-size: 1.6rem; line-height: 1; cursor: pointer; border-radius: 8px;
}
.tsdp-close:hover { background: var(--bg-alt, #f6f3f0); }
.tsdp-close:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: 2px; }

.tsdp-eyebrow { font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-secondary, #5d6470); }
.tsdp-title { margin: 6px 0 14px; font-size: 1.22rem; line-height: 1.3; padding-right: 28px; }

.tsdp-single { display: grid; gap: 4px; }
.tsdp-show { font-weight: 700; }
.tsdp-type { color: var(--text-secondary, #5d6470); }
.tsdp-left { margin: 8px 0 2px; font-size: 1.45rem; font-weight: 800; letter-spacing: .01em;
  color: var(--c, #c0392b); }
.tsdp-when { color: var(--text-secondary, #5d6470); font-size: .9rem; }

.tsdp-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.tsdp-list li { display: flex; align-items: flex-start; gap: 10px; }
.tsdp-dot { flex: 0 0 auto; margin-top: 6px; width: 9px; height: 9px; border-radius: 50%;
  background: var(--c, #6b7280); }
.tsdp-meta { display: block; color: var(--text-secondary, #5d6470); font-size: .86rem; }

.tsdp-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 18px; }
.tsdp-btn {
  flex: 1 1 auto; text-align: center; padding: 10px 14px; border-radius: 8px;
  border: 1px solid var(--border-subtle, #e3dcd5); background: transparent; color: inherit;
  font-size: .9rem; font-weight: 600; text-decoration: none; cursor: pointer;
}
.tsdp-btn:hover { border-color: var(--accent, #ff6b4a); }
.tsdp-btn:focus-visible { outline: 2px solid var(--accent, #ff6b4a); outline-offset: 2px; }
.tsdp-primary { background: var(--accent, #ff6b4a); border-color: var(--accent, #ff6b4a); color: #12141a; }
.tsdp-quiet { color: var(--text-secondary, #5d6470); }

/* ---- reduced motion --------------------------------------------------------------------- */
/* No pulse, no transition. The urgency is carried by a heavier static border instead, so the
   signal survives without any movement at all. */
@media (prefers-reduced-motion: reduce) {
  /* The same rule the homepage already applies to .marquee-track: the strip stops rather than
     slows, and every item stays reachable through the panel and the screen-reader list. */
  .tsd-track { animation: none !important; }
  /* The breathing stops too, at full opacity rather than mid-fade. The urgency is still carried
     by the colour and the countdown pill, so nothing is lost by holding still. */
  .tsd-item.u-strong .tsd-dot, .tsd-item.u-strong .tsd-left,
  .tsd-item.u-red .tsd-dot, .tsd-item.u-red .tsd-left {
    animation: none !important;
    opacity: 1 !important;
  }
  .tsdp-card, .tsdp-btn { transition: none; }
}

@media (max-width: 760px) {
  /* The gap under the video closes up at narrow widths, so there is nothing left to centre in -
     the lift would pull the strip onto the video itself. */
  .ts-deadlines { top: 0; }
}

@media (max-width: 480px) {
  /* The date goes first: the show name and the countdown are what a visitor needs, and the panel
     behind the click lists every date in full. */
  .tsd-date { display: none; }
  .tsd-track { gap: 40px; }
  .tsdp-actions { flex-direction: column; }
  .tsdp-btn { flex: 1 1 auto; }
}
