[hidden] {
  display: none !important;
}

/* The artboard's phone IS the column: `padding: var(--space-6) var(--space-6)
 * var(--space-4)`, brand first, reading centred, footnote last. The body is
 * that column, so the brand sits in the same padding box as everything under
 * it instead of being pinned to a corner and lined up by hand. A body
 * background still paints the whole canvas when the body is narrower than the
 * viewport, so the wider-screen max-width costs nothing. */
body.access-page {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  width: 100%;
  max-width: 460px;
  min-height: 100svh;
  margin: 0 auto;
  padding: var(--space-6) var(--space-6) var(--space-4);
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  overflow-x: hidden;
}

/* Top of the column, at the artboard's 20px, in the brand's own colour.
 * `.nav-brand` (composed in markup) supplies the face and weight; the size is
 * the surface's own — a phone opened from a camera, not a header bar. Not a
 * target: no href, no tabindex, no :focus-visible — there is nothing on this
 * route for a keyboard to reach. */
.access-home {
  flex: none;
  margin-right: 0;
  font-size: 20px;
}

/* Everything under the brand: the reading takes the free height and centres in
 * it, the footnote closes the column. Clipping is what keeps the decorative
 * wash from widening the document. */
.access-route {
  display: flex;
  position: relative;
  flex: 1 0 auto;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  text-align: start;
}

/* The artboard's soft organic shape behind the wait — accent-2, blurred, bled
 * off the top-right corner and clipped by the column. Decorative geometry, so
 * the offsets are the artboard's own numbers rather than spacing tokens. */
.atmosphere {
  display: none;
  position: absolute;
  z-index: 0;
  top: -180px;
  right: -90px;
  width: 340px;
  height: 340px;
  border-radius: 52% 48% 42% 58%;
  background: radial-gradient(
    circle at 40% 35%,
    var(--color-accent-2-300),
    var(--color-accent-2-200) 55%,
    transparent 75%
  );
  opacity: 0.55;
  filter: blur(14px);
  pointer-events: none;
}

.access-route[data-state="loading"] .atmosphere {
  display: block;
}

/* Centred in the free height, flush left. The Organic system's own rule is
 * "left-aligned, flush-left headings; whitespace on the right", and a centred
 * column of three different line lengths gives a Guest three different places
 * to start reading. */
.access-card {
  display: flex;
  position: relative;
  z-index: 1;
  flex: 1 0 auto;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-3);
  min-width: 0;
}

/* Which code this screen is about, before anything else is read. */
.access-eyebrow {
  margin: 0;
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.access-live {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  min-width: 0;
}

#access-heading {
  margin: 0;
  font-size: clamp(28px, 9.8vw, 38px);
  line-height: 1.1;
}

/* The state's mark and its sentence, side by side while the scan is in flight
 * and stacked once it has settled. */
.access-report {
  display: flex;
  position: relative;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
  margin-top: var(--space-2);
}

/* The state mark. aria-hidden: every distinction it draws is already stated in
 * words beside it, so nothing here is the only carrier of a meaning. The
 * artboard draws it at the scale of the sentence it sits next to — a 14px ring
 * with one lit quadrant, not a badge above the heading. */
.access-mark {
  display: grid;
  flex: none;
  place-items: center;
  width: 14px;
  height: 14px;
  margin: 0;
}

.access-mark-glyph {
  width: 14px;
  height: 14px;
  border: 3px solid var(--color-accent-300);
  border-radius: 999px;
}

/* Loading: the lit quadrant turns. Cancelled under reduced motion
 * (organic-system.css has no blanket animation cancel — only this surface's
 * own animation needs one); the state stays named in the heading either way,
 * and browser/access.spec.js checks the computed animation-name directly. */
.access-route[data-state="loading"] .access-mark-glyph,
.access-route[data-state="committed"] .access-mark-glyph {
  border-top-color: var(--color-accent);
}

.access-route[data-state="loading"] .access-mark-glyph {
  animation: access-mark-turn 1.1s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
  .access-route[data-state="loading"] .access-mark-glyph {
    animation: none;
  }
}

@keyframes access-mark-turn {
  to {
    transform: rotate(360deg);
  }
}

/* Committed is the one state the artboard does not draw, so it borrows the
 * wait's own row with the ring settled rather than turning. */
.access-route[data-state="committed"] .access-mark-glyph {
  border-color: var(--color-accent);
}

/* A refusal and an outage carry no mark at all in the artboard — the remedy
 * panel is the whole of what they show. */
.access-route[data-state="failure"] .access-mark,
.access-route[data-state="offline"] .access-mark {
  display: none;
}

.access-message {
  min-width: 0;
  margin: 0;
  font-size: 15px;
  line-height: 1.5;
}

/* The wait's sentence is the quiet half of the pair, in the second accent. */
.access-route[data-state="loading"] .access-message,
.access-route[data-state="committed"] .access-message {
  color: var(--color-accent-2-700);
}

/* The remedy is a panel, as the artboard draws it: the refusal on the
 * terracotta ramp, the outage on the second accent, because an outage is the
 * one of the two a Guest can clear without walking anywhere. Text sits at the
 * dark end of its own ramp — design.md's answer for a serious note without
 * inventing a red. */
.access-route[data-state="failure"] .access-message,
.access-route[data-state="offline"] .access-message {
  flex: 1;
  padding: var(--space-4);
  border-radius: var(--radius-lg);
}

.access-route[data-state="failure"] .access-message {
  background: var(--color-accent-100);
  color: var(--color-accent-800);
}

.access-route[data-state="offline"] .access-message {
  background: var(--color-accent-2-100);
  color: var(--color-accent-2-800);
}

/* `.error-text` is a hook browser/access.spec.js checks by class name, not a
 * visual departure: the panel above already carries the colour, and a refusal
 * stays secondary to its heading. */
#access-status.error-text {
  font-weight: 400;
}

/* The line that closes the column. The artboard gives every state its own —
 * the wait says what happens next, the refusals say what the desk can do — so
 * it is written from `access.js` and never hidden. */
.access-help {
  flex: none;
  margin: var(--space-6) 0 0;
  font-size: 12.5px;
  line-height: 1.5;
}

@media (prefers-reduced-motion: reduce) {
  .access-page * {
    transition: none;
  }
}
