:root {
    --ink: #1d1d1f;
    --muted: #515154;
    --accent: #0a66c2;
    --radius: 12px;
    --screen: #ffffff;
    /* The page's one motion source: a curve and a duration per kind of change. app.js
       reads these too. The screen colour itself never moves: the check needs it at once. */
    --motion-curve: cubic-bezier(0.16, 1, 0.3, 1);
    --motion-press: 120ms;
    --motion-colour: 240ms;
    --motion-show: 200ms;
    --ring: #c7c7cc; /* The outline's edge; green once the face fills it. */
    --ring-fits: #34c759;
    color-scheme: light;
}

* {
    box-sizing: border-box;
}

html,
body {
    margin: 0;
    height: 100%;
    background: var(--screen);
    color: var(--ink);
    font:
        17px/1.5 -apple-system,
        BlinkMacSystemFont,
        'Segoe UI',
        'PingFang SC',
        sans-serif;
    -webkit-text-size-adjust: 100%;
}

body {
    transition: none; /* The colour must change at once, never fade. */
}

/* Signing in a computer, on the phone: what signs in, "this wasn't me" away from the thumb, the numbers at the bottom. */
.hand-detail {
    color: var(--muted);
    font-size: 15px;
}

.hand-warning {
    font-weight: 600;
}

.link {
    min-height: 44px;
    padding: 0;
    border: 0;
    background: none;
    color: var(--accent);
    font: inherit;
    cursor: pointer;
}

.pick-how {
    text-align: center;
}

.pick-numbers {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-bottom: 16px;
}

.pick-number {
    min-height: 64px;
    border: 1px solid var(--ring);
    border-radius: var(--radius);
    background: #fff;
    color: var(--ink);
    font: inherit;
    font-size: 28px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    cursor: pointer;
    transition: transform var(--motion-press) var(--motion-curve);
}

.pick-number:active {
    transform: scale(0.97);
}

/* The computer's page (/laptop): the code, its number, how the sign-in stands. */
.desk {
    max-width: 560px;
    margin: 0 auto;
    padding: 48px 24px;
    text-align: center;
}

.desk-code {
    margin: 24px 0;
}

/* Its room is kept from the first frame, so the code's arrival moves nothing below it. */
.desk-qr {
    width: min(70vw, 280px);
    aspect-ratio: 1;
    margin: 0 auto 16px;
}

.desk-qr svg {
    display: block;
    width: 100%;
    height: 100%;
}

.desk-label {
    display: block;
    color: var(--muted);
    font-size: 15px;
}

.desk-number {
    display: block;
    min-height: 1.5em; /* Its line kept before the number comes, so nothing below moves. */
    font-size: 56px;
    letter-spacing: 0.08em;
    font-variant-numeric: tabular-nums;
}

.desk-status {
    color: var(--muted);
}

.desk[data-state='passed'] .desk-status {
    color: var(--ink);
    font-weight: 600;
}

.desk[data-state='passed'] .desk-code,
.desk[data-state='refused'] .desk-code,
.desk[data-state='failed'] .desk-code {
    visibility: hidden;
}

/* The light lab (/lab): the layer its ways of painting the screen go in, behind the page. */
.hdr {
    position: fixed;
    inset: 0;
    z-index: 0;
    overflow: hidden;
}

.hdr > * {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: fill;
    z-index: 0;
}

.hdr-plain {
    background: var(--screen);
}

/* The page above that layer, all of it: without a stacking order of its own, its unpositioned text sat under the
   layer's plain white and showed only while it faded in (review of HDR in the check). */
.stage {
    position: relative;
    z-index: 1;
}

.stage {
    min-height: 100svh; /* In flow: svh, so the phone's browser bar moving never resizes it. */
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: max(16px, env(safe-area-inset-top)) max(20px, env(safe-area-inset-right))
        max(24px, env(safe-area-inset-bottom)) max(20px, env(safe-area-inset-left));
    max-width: 560px;
    margin: 0 auto;
}

/* The face outline: a face's shape, wider at the brow than at the chin, width:height 3:4
   (OUTLINE_ASPECT in liveness/constants.py: the server measures the face against it). */
.outline {
    /* Short phones (375 x 548 visible: an iPhone SE with Safari's bars) keep Start in the
       first view: the outline is at most 39% of the visible height tall (3:4: 29% wide). */
    position: relative;
    width: min(72vw, 300px, 29svh);
    aspect-ratio: 3 / 4;
    border-radius: 50% / 44% 44% 56% 56%; /* flatter brow, longer taper to the chin */
    overflow: hidden;
    background: #e5e5ea;
    box-shadow: 0 0 0 4px var(--ring);
    transition: box-shadow var(--motion-colour) var(--motion-curve);
    flex: none;
    margin-top: 12px;
}

.stage[data-hint='hold'] .outline {
    box-shadow: 0 0 0 4px var(--ring-fits);
}

.preview {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transform: scaleX(-1);
}

/* The picture itself (static/preview.js), over the video that feeds it. */
.picture {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    transform: scaleX(-1);
}

.copy {
    flex: 1;
    width: 100%;
    padding-top: 12px;
}

h1 {
    font-size: 24px;
    line-height: 1.25;
    margin: 0 0 8px;
}

p {
    margin: 0 0 12px;
}

.warning {
    color: var(--muted);
    font-size: 15px;
}

.tip {
    color: var(--muted);
    font-size: 15px;
    text-align: center;
}

.actions {
    width: 100%;
}

.primary {
    width: 100%;
    min-height: 52px;
    border: 0;
    border-radius: var(--radius);
    background: var(--accent);
    color: #fff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
    transition:
        background-color var(--motion-colour) var(--motion-curve),
        opacity var(--motion-colour) var(--motion-curve),
        transform var(--motion-press) var(--motion-curve);
}

.primary:active:not(:disabled) {
    transform: scale(0.97);
}

.primary:disabled {
    opacity: 0.5;
    cursor: default;
}

/* Both labels stay mounted in one cell, so the button keeps the wider one's width and
   the shown one names it; the hidden one is aria-hidden and inert. */
.label-swap {
    display: inline-grid;
}

.label-swap > span {
    grid-area: 1 / 1;
    opacity: 1;
    visibility: inherit;
    transition: opacity var(--motion-show) var(--motion-curve);
}

.label-swap > span[aria-hidden='true'] {
    opacity: 0;
    visibility: hidden;
    transition:
        opacity var(--motion-show) var(--motion-curve),
        visibility 0s linear var(--motion-show);
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        transition-duration: 0s !important;
        transition-delay: 0s !important;
        animation-duration: 0s !important;
        animation-delay: 0s !important;
    }

    .primary:active:not(:disabled),
    .pick-number:active {
        transform: none;
    }
}

.result {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 12px;
    font-size: 15px;
    margin: 12px 0 0;
}

.result[hidden] {
    display: none; /* The grid above would otherwise override the hidden attribute. */
}

.result dt {
    font-weight: 600;
}

.result dd {
    margin: 0;
    color: var(--muted);
}

.result .verdict {
    grid-column: 1 / -1;
    font-size: 20px;
    font-weight: 700;
    color: var(--ink);
}

/* While colours show, only the colour and the face in its outline are on screen: the text
   and the button step aside so the colour fills all the rest, and the face stays visible so
   the person can keep it in the outline (the owner, 2026-11-06). */
.stage[data-state='colours'] .copy,
.stage[data-state='colours'] .actions {
    visibility: hidden;
}

/* The one word the person needs during the colours, on any colour: a white pill, small enough
   to take almost no light from the screen. */
.cue {
    position: fixed;
    left: 50%;
    top: 66svh;
    transform: translateX(-50%);
    margin: 0;
    padding: 10px 22px;
    border-radius: var(--radius);
    background: #fff;
    color: var(--ink);
    font-size: 26px;
    font-weight: 700;
    white-space: nowrap;
}

/* Stays in the page, empty: a status revealed with its words already in it is not announced. */
.cue:empty {
    padding: 0;
}

.result .why {
    grid-column: 1 / -1;
    margin: 0 0 6px;
    color: var(--ink);
}
