/* isopennow.com
   Palette is keyed to the trading day: warm amber for Asia-Pacific, violet for
   EMEA, teal for the Americas, and one hot signal red reserved exclusively for
   the "now" marker so the eye always finds the present moment first.

   Every token below carries what it is for and its contrast against the two
   surfaces text actually sits on (--ink, the page, and --ink-2, cards and
   panels). WCAG AA wants 4.5:1 for body text, and everything in the text ramp
   clears it on both. Colour never carries meaning alone anywhere on the site:
   an open market is green AND says "Open". If you add a token, measure it. */

:root {
  /* surfaces */
  --ink:      #12161F;   /* page ground */
  --ink-2:    #191F2C;   /* cards, panels, the ribbon frame */
  --ink-3:    #212938;   /* card hover, empty ribbon track */
  --line:     #2B3446;   /* hairline rules and card borders */

  /* text ramp - three levels, each roughly twice the luminance of the next */
  --text:     #E7EBF3;   /* primary            15.1:1 on ink, 13.8:1 on ink-2 */
  --muted:    #A3AEC4;   /* secondary prose     8.1:1 on ink,  7.4:1 on ink-2 */
  --dim:      #7C879B;   /* labels, countdowns  5.0:1 on ink,  4.6:1 on ink-2 */

  /* regions - the ribbon bars, and the swatch that repeats that colour wherever
   a market is named, so the same market reads the same everywhere */
  --asia:     #E8A33D;
  --europe:   #8C7BE8;
  --americas: #3FB6A8;
  --global:   #5AA9E6;

  /* state - always paired with the word, never used alone */
  --open:     #4ADE80;   /* "Open"                              9.5:1 on ink-2 */
  --break:    #E8A33D;   /* "Lunch break", and the ribbon hatch 7.6:1 on ink-2 */
  --shut:     #6B7689;
  --now:      #FF5C6E;   /* reserved: the now marker only       5.5:1 on ink-2 */

  /* System fonts only. Nothing is fetched from a third party, so the pages make
     no outbound request at all: no font-provider request means no visitor IP
     handed to anyone, nothing to disclose, and no render-blocking stylesheet
     from a host we do not control. Whatever the reader's OS ships is already
     on their disk and already hinted for their screen. */
  --display: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;

  --wrap: 74rem;
  --r: 10px;
}

*, *::before, *::after { box-sizing: border-box; }

/* One swatch, used in the ribbon labels and in the hours table. Its colour
   comes from --swatch, which the region class sets on an ancestor, so a market
   carries the same colour wherever its name appears. */
.swatch {
  display: inline-block; flex: none;
  width: .6rem; height: .6rem; border-radius: 2px;
  background: var(--swatch, var(--dim));
  vertical-align: baseline;
}
.swatch--asia,     .tbl__group--asia     { --swatch: var(--asia); }
.swatch--europe,   .tbl__group--europe   { --swatch: var(--europe); }
.swatch--americas, .tbl__group--americas { --swatch: var(--americas); }
.swatch--global,   .tbl__group--global   { --swatch: var(--global); }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--body);
  font-size: 16px;
  line-height: 1.6;
  /* faint horizon glow, so the page is not a flat rectangle of dark */
  background-image: radial-gradient(120% 60% at 50% -10%, #1B2333 0%, var(--ink) 60%);
  background-repeat: no-repeat;
}

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: -999px; top: 0; z-index: 99;
  background: var(--now); color: #fff; padding: .6rem 1rem; border-radius: 0 0 var(--r) 0;
}
.skip:focus { left: 0; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--now);
  outline-offset: 3px;
  border-radius: 3px;
}

/* ---------- masthead ---------- */

.masthead {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem;
  max-width: var(--wrap); margin: 0 auto; padding: 1.4rem 1.25rem 1rem;
}

.wordmark {
  display: inline-flex; align-items: center; gap: .55rem;
  font-family: var(--display);
  font-weight: 800;
  font-size: 1.1rem;
  letter-spacing: -.02em;
  text-decoration: none;
}
.wordmark em { font-style: normal; color: var(--muted); }
.wordmark__dot {
  width: .55rem; height: .55rem; border-radius: 50%;
  background: var(--open);
  box-shadow: 0 0 0 4px rgba(74, 222, 128, .14);
}

.masthead__clock { text-align: right; font-family: var(--mono); font-size: .8rem; }
.masthead__clock time { display: block; font-size: 1rem; color: var(--text); }
.masthead__clock .lbl { color: var(--dim); font-size: .7rem; letter-spacing: .09em; text-transform: uppercase; }
.masthead__clock .tzname { color: var(--dim); font-size: .7rem; }

/* ---------- hero ---------- */

.hero { max-width: var(--wrap); margin: 0 auto; padding: 2rem 1.25rem 1.5rem; }

.eyebrow {
  font-family: var(--mono);
  font-size: .72rem; letter-spacing: .16em; text-transform: uppercase;
  color: var(--dim); margin: 0 0 .9rem;
}
.eyebrow a { color: var(--muted); }

h1 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2rem, 6.2vw, 3.9rem);
  line-height: 1.02;
  letter-spacing: -.035em;
  margin: 0 0 1rem;
}
h1 em { font-style: normal; color: var(--now); }

.lede { color: var(--muted); font-size: 1.03rem; margin: 0; }

/* The count. The page cannot answer "is anything open" in its HTML - that is
   the whole point of computing status in the browser - so the number arrives a
   frame later and the markup ships a dash, not a claim. */
.tally {
  display: flex; align-items: center; gap: .85rem;
  margin: 1.4rem 0 1.2rem;
}
/* The breakdown belongs to the number, so it sits against it. Pushing it to
   the far edge of a 74rem container opens a gap you have to cross to read
   one short line. */
.tally__text { display: flex; flex-direction: column; gap: .1rem; }
.tally__num {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(2.6rem, 8vw, 4rem);
  line-height: .9;
  letter-spacing: -.045em;
  color: var(--open);
  font-variant-numeric: tabular-nums;
}
.tally[data-any="no"] .tally__num { color: var(--muted); }
.tally__of {
  font-family: var(--display);
  font-weight: 700; font-size: 1.2rem; letter-spacing: -.01em; line-height: 1.15;
}
.tally__rest { font-family: var(--mono); font-size: .78rem; color: var(--dim); }

/* ---------- ribbon (the signature element) ---------- */

.ribbon-wrap { max-width: var(--wrap); margin: 0 auto; padding: 1rem 1.25rem 2.5rem; }

/* One line, and only the thing the chart cannot say for itself: whose clock
   the scale is on. What the colours and the hatch mean is in the legend, six
   inches lower, next to the swatches. */
.ribbon__caption {
  font-family: var(--mono);
  font-size: .72rem; letter-spacing: .12em; text-transform: uppercase;
  color: var(--dim);
  margin: 0 0 .6rem;
}

.ribbon {
  /* Label gutter. The scale, the rows, the now marker and the legend all
     align to it, so it lives here and nowhere else. Wide enough for the
     longest name in the data (Euronext Paris). */
  --label-w: 8.2rem;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1rem .9rem .5rem;
  position: relative;
  overflow: hidden;
}
.ribbon__loading { color: var(--dim); font-family: var(--mono); font-size: .85rem; padding: 2rem 0; text-align: center; }

.ribbon__scale {
  display: flex; position: relative; height: 1.1rem;
  margin-left: var(--label-w); margin-bottom: .5rem;
  font-family: var(--mono); font-size: .66rem; color: var(--dim);
}
.ribbon__tick { position: absolute; transform: translateX(-50%); white-space: nowrap; }

.ribbon__row {
  display: grid;
  grid-template-columns: var(--label-w) 1fr;
  align-items: center;
  gap: 0;
  padding: .16rem 0;
}
.ribbon__row:hover .ribbon__label { color: var(--text); }

.ribbon__label {
  display: flex; align-items: center; gap: .45rem;
  font-family: var(--mono); font-size: .74rem; color: var(--muted);
  text-decoration: none; padding-right: .6rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ribbon__label .swatch { width: .5rem; height: .5rem; }

.ribbon__track {
  position: relative;
  height: 1.15rem;
  background: var(--ink-3);
  border-radius: 3px;
  overflow: hidden;
}

.ribbon__seg {
  position: absolute; top: 0; bottom: 0;
  border-radius: 2px;
  opacity: .85;
}
.ribbon__seg--asia     { background: var(--asia); }
.ribbon__seg--europe   { background: var(--europe); }
.ribbon__seg--americas { background: var(--americas); }
.ribbon__seg--global   { background: var(--global); }
.ribbon__seg--ext      { opacity: .3; }

/* The midday break is drawn, not left as a hole. An unmarked gap between two
   session blocks reads as "closed", when in fact the exchange is open and
   simply not matching orders - which is the single most misread hour of the
   Asian trading day. */
.ribbon__seg--lunch {
  background-image: repeating-linear-gradient(
    135deg, var(--break) 0 2px, transparent 2px 5px);
  opacity: .6;
  border-radius: 0;
}

/* A market somebody stopped by hand.
   Grey, because that is the palette's closed colour, and hatched, because a
   halt is an event rather than a state the schedule knows about. Denser than
   the midday break so the two never read as the same thing, and deliberately
   not --now: that red belongs to the now marker alone. */
.ribbon__seg--suspended {
  background-image: repeating-linear-gradient(
    135deg, var(--shut) 0 3px, transparent 3px 6px);
  background-color: rgba(107, 118, 137, .18);
  opacity: .85;
  border-radius: 0;
}

.ribbon__now {
  position: absolute; top: 0; bottom: 0; width: 2px;
  background: var(--now);
  z-index: 5;
  pointer-events: none;
}
.ribbon__nowlane { position: absolute; left: var(--label-w); right: .9rem; top: 0; bottom: 0; pointer-events: none; }
.ribbon__nowlane .ribbon__now { box-shadow: 0 0 12px 1px rgba(255, 92, 110, .55); }

.ribbon__nowlabel {
  position: absolute; top: 0; transform: translateX(-50%);
  font-family: var(--mono); font-size: .62rem; color: var(--now);
  background: var(--ink-2); padding: 0 .3rem; white-space: nowrap;
}

.ribbon--single { margin: 1.5rem 0 0; padding: .9rem; }

.ribbon__legend {
  display: flex; flex-wrap: wrap; gap: .25rem 1.1rem;
  margin: .9rem 0 .3rem var(--label-w);
  font-family: var(--mono); font-size: .68rem; color: var(--dim);
}
.ribbon__legend span { display: inline-flex; align-items: center; gap: .35rem; }
.ribbon__legend i { width: .7rem; height: .55rem; border-radius: 2px; display: inline-block; }
.ribbon__legend i.hatch {
  background-image: repeating-linear-gradient(
    135deg, var(--break) 0 2px, transparent 2px 5px);
  background-color: var(--ink-3);
}

.ribbon__legend i.hatch--suspended {
  background-image: repeating-linear-gradient(
    135deg, var(--shut) 0 3px, transparent 3px 6px);
}

/* ---------- board ---------- */

.board { max-width: var(--wrap); margin: 0 auto; padding: 0 1.25rem 3rem; }
.board h2, .prose h2, .panel h2 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.25rem;
  letter-spacing: -.015em;
  margin: 0 0 1rem;
}

.board__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: .7rem;
}

.card {
  display: block; text-decoration: none;
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line);
  border-radius: var(--r);
  padding: .85rem .95rem;
  transition: border-color .15s ease, transform .15s ease, background .15s ease;
}
.card:hover { background: var(--ink-3); transform: translateY(-1px); }
/* --ink-3 is the one surface where --dim drops under 4.5:1, so lift the
   secondary line on hover rather than leave it below the line. */
.card:hover .card__sub { color: var(--muted); }
.card[data-open="open"]   { border-left-color: var(--open); }
.card[data-open="break"]  { border-left-color: var(--break); }
.card[data-open="closed"] { border-left-color: var(--line); }

.card__top { display: flex; align-items: baseline; justify-content: space-between; gap: .5rem; }
.card__name { font-weight: 700; font-size: .98rem; letter-spacing: -.01em; }
.card__time { font-family: var(--mono); font-size: .85rem; color: var(--muted); }
.card__state {
  font-family: var(--mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  margin-top: .45rem; display: flex; align-items: center; gap: .4rem;
}
.card[data-open="open"]   .card__state { color: var(--open); }
.card[data-open="break"]  .card__state { color: var(--break); }
.card[data-open="closed"] .card__state { color: var(--dim); }
.card__sub { font-size: .82rem; color: var(--dim); margin-top: .2rem; }

.dot { width: .45rem; height: .45rem; border-radius: 50%; background: currentColor; flex: none; }
.card[data-open="open"] .dot { animation: pulse 2.4s ease-in-out infinite; }

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, .5); }
  50%      { box-shadow: 0 0 0 5px rgba(74, 222, 128, 0); }
}

/* ---------- exchange page ---------- */

.ex { max-width: var(--wrap); margin: 0 auto; padding: 1.5rem 1.25rem 3rem; }

.verdict {
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 1.4rem 1.4rem 1.5rem;
  margin: 1.2rem 0 0;
  position: relative;
  overflow: hidden;
}
.verdict::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--line);
}
.verdict[data-open="open"]::before   { background: var(--open); }
.verdict[data-open="break"]::before  { background: var(--break); }
.verdict[data-open="closed"]::before { background: var(--now); }

.verdict__state {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.7rem, 5.5vw, 2.6rem);
  letter-spacing: -.03em;
  line-height: 1.05;
  margin: 0 0 .5rem;
}
.verdict[data-open="open"]   .verdict__state { color: var(--open); }
.verdict[data-open="break"]  .verdict__state { color: var(--break); }
.verdict[data-open="closed"] .verdict__state { color: var(--text); }

.verdict__why { margin: 0; color: var(--muted); }
.verdict__next { margin: .7rem 0 0; font-family: var(--mono); font-size: .88rem; color: var(--text); }

.clocks {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: .7rem;
  margin: .7rem 0 0;
}
.clock {
  background: var(--ink-2); border: 1px solid var(--line); border-radius: var(--r);
  padding: .7rem .8rem;
}
.clock .lbl {
  display: block; font-family: var(--mono); font-size: .68rem;
  letter-spacing: .1em; text-transform: uppercase; color: var(--dim);
}
.clock__t { display: block; font-family: var(--mono); font-size: 1.15rem; margin: .15rem 0; }
.clock .tzname { font-size: .7rem; color: var(--dim); font-family: var(--mono); }

.panel { margin: 2.2rem 0 0; }

.kv { display: grid; grid-template-columns: max-content 1fr; gap: .35rem 1.5rem; margin: 0; }
.kv dt { color: var(--muted); font-size: .9rem; }
.kv dd { margin: 0; }

.note { color: var(--muted); font-size: .92rem; margin: 1rem 0 0; }

.warn {
  border: 1px solid rgba(232, 163, 61, .35);
  background: rgba(232, 163, 61, .07);
  color: var(--asia);
  border-radius: var(--r);
  padding: .8rem 1rem;
  font-size: .88rem;
  margin: 2rem 0 0;
}

.chips { display: flex; flex-wrap: wrap; gap: .4rem; }
.chip {
  display: inline-flex; align-items: center; gap: .4rem;
  text-decoration: none;
  background: var(--ink-2); border: 1px solid var(--line);
  border-radius: 100px; padding: .3rem .75rem;
  font-size: .85rem; color: var(--muted);
}
.chip:hover { color: var(--text); border-color: var(--dim); }
.chip__dot { width: .4rem; height: .4rem; border-radius: 50%; background: var(--dim); flex: none; }
.chip[data-open="open"] .chip__dot  { background: var(--open); }
.chip[data-open="break"] .chip__dot { background: var(--break); }

/* ---------- tables + prose ---------- */

/* Text runs the full width of its container everywhere on this site. There are
   no measure caps and no column tricks: a capped paragraph inside a wider
   container leaves a dead half-page beside it, and splitting a few sentences
   into columns makes the eye travel down and back up for no gain. One column,
   wall to wall. */
.prose { max-width: var(--wrap); margin: 0 auto; padding: 0 1.25rem 3rem; }
.prose p { color: var(--muted); }

/* A heading that follows a table needs air, or it reads as the table's last
   row. The shared h2 rule sets no top margin because most h2s open a section. */
.prose h2:not(:first-child) { margin-top: 3rem; }
.prose h3 {
  font-family: var(--display);  font-weight: 700; font-size: 1rem; margin: 1.6rem 0 .4rem; color: var(--text);
}

.table-scroll { overflow-x: auto; }

.tbl { width: 100%; border-collapse: collapse; font-size: .9rem; }
.tbl th, .tbl td { text-align: left; padding: .55rem .7rem; border-bottom: 1px solid var(--line); }
.tbl thead th {
  font-family: var(--mono); font-size: .7rem; letter-spacing: .1em;
  text-transform: uppercase; color: var(--dim); font-weight: 400;
}
.tbl tbody th { font-weight: 600; }
.tbl tbody th a { text-decoration: none; }
.tbl tbody th a:hover { color: var(--asia); }
.tbl .num, .num { font-family: var(--mono); }
.tbl .muted, .muted { color: var(--dim); }
.tbl--dates td:first-child { width: 11rem; white-space: nowrap; }

/* ---------- the hours table ---------- */

/* Grouped by region rather than run as one 20-row block: the eye finds
   "which European exchange" without reading the timezone column. */
.tbl--hours { font-size: .92rem; }
.tbl--hours tbody tr:hover { background: var(--ink-2); }
.tbl--hours tbody th, .tbl--hours tbody td { padding: .6rem .7rem; }

.tbl__grouphead th {
  font-family: var(--mono);
  font-size: .68rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 500;
  color: var(--swatch);
  padding: 2rem .7rem .5rem;
  border-bottom: 1px solid var(--line);
}
.tbl__grouphead th .swatch { margin-right: .5rem; }
.tbl__group:first-of-type .tbl__grouphead th { padding-top: .4rem; }
.tbl--hours tbody tr.tbl__grouphead:hover { background: none; }

.tbl--hours tbody th a {
  display: inline-flex; align-items: center; gap: .55rem;
  text-decoration: none;
}
.tbl__short { font-weight: 700; letter-spacing: -.01em; }
.tbl__city { color: var(--dim); font-size: .88em; }
.tbl--hours tbody th a:hover .tbl__short { color: var(--text); }
.tbl--hours tbody th a:hover .tbl__city { color: var(--muted); }

/* Neutral by design: the pill says what it means in words, so it does not
   need to borrow a colour that means something else on this page. */
.pill {
  display: inline-block;
  font-family: var(--mono); font-size: .66rem;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--dim);
  border: 1px solid var(--line); border-radius: 100px;
  padding: .1rem .55rem;
  white-space: nowrap;
}
.pill--on { color: var(--muted); border-color: var(--dim); }


/* ---------- footer ---------- */

.foot {
  border-top: 1px solid var(--line);
  max-width: var(--wrap); margin: 2rem auto 0; padding: 1.6rem 1.25rem 3rem;
  color: var(--dim); font-size: .84rem;
}

.foot strong { color: var(--muted); }
.foot__nav { display: flex; flex-wrap: wrap; gap: .3rem .9rem; margin: 1rem 0; }
.foot__nav a { color: var(--dim); text-decoration: none; font-family: var(--mono); font-size: .78rem; }
.foot__nav a:hover { color: var(--text); }
.foot__meta { font-family: var(--mono); font-size: .72rem; }

/* ---------- responsive ---------- */

@media (max-width: 640px) {
  .ribbon { --label-w: 5.2rem; }
  .ribbon__label { font-size: .68rem; }
  .clocks { grid-template-columns: 1fr; }
  .kv { grid-template-columns: 1fr; gap: 0 0; }
  .kv dt { margin-top: .5rem; }
  .masthead__clock time { font-size: .9rem; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}
