/*
 * AIMcom console.
 *
 * A working tool used under time pressure in a busy venue, not a marketing
 * surface. Three rules follow from that and every choice below is one of them:
 *
 *   1. Clarity and density over decoration. One accent colour for anything
 *      interactive. The other colours in here are state, not styling: a
 *      provisional booking, a breached latency ceiling and a disabled channel
 *      each have to be identifiable without reading the label.
 *   2. Generous type. The board is read across a room and the bookings list is
 *      read on a tablet on a host stand, so the base size is 16px and the
 *      board's own figures are much larger.
 *   3. No dependency. System fonts, no icon font, no web font. The console has
 *      to work with no network beyond the application itself.
 */

:root {
    /*
     * Aimatric brand palette, taken from aimatric.com. Teal is the brand and
     * carries structure: navigation, links, focus. Orange is the action colour
     * and is reserved for the one primary control on a screen. That division
     * is how the marketing site uses them, and it happens to be right for a
     * dense operational tool as well: if every link were orange, nothing would
     * read as the thing to press.
     */
    --accent: #0E6E7C;          /* teal-700 */
    --accent-strong: #0A4A54;   /* teal-900 */
    --accent-wash: #EDFBFD;     /* teal-50  */

    --action: #F97316;          /* orange-500, primary control only */
    --action-strong: #EA580C;   /* orange-600 */

    --ink: #111827;             /* gray-900 */
    --ink-soft: #4B5563;        /* gray-600 */
    --ink-faint: #6B7280;       /* gray-500 */
    --page: #F9FAFB;            /* gray-50  */
    --card: #FFFFFF;
    --line: #E5E7EB;            /* gray-200 */
    --line-soft: #F3F4F6;       /* gray-100 */

    /*
     * State. Not decoration: each of these carries a fact, and each is darker
     * than the brand equivalent would be because it sits behind text on white
     * and has to stay legible on a tablet at arm's length. The brand's
     * --success #10B981 is used for the indicator dot, not for the label.
     */
    --state-good: #047857;
    --state-good-wash: #ECFDF5;
    --state-good-dot: #10B981;
    --state-warn: #9A3412;
    --state-warn-wash: #FFF7ED;
    --state-bad: #B91C1C;
    --state-bad-wash: #FEF2F2;
    --state-idle: #4B5563;
    --state-idle-wash: #F3F4F6;

    --radius: 8px;
    --gap: 1rem;
    --shadow: 0 1px 2px rgba(10, 74, 84, .08), 0 1px 8px rgba(10, 74, 84, .05);

    /*
     * Inter is the Aimatric typeface. It is self-hosted rather than pulled
     * from a font CDN, because the console must work with no network beyond
     * the application itself. If the file is absent the @font-face simply does
     * not resolve and the system stack takes over, which is a degradation
     * nobody notices rather than a failure.
     */
    --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
            "Helvetica Neue", Arial, "Noto Sans", sans-serif;
    --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
            "Liberation Mono", monospace;
}

@font-face {
    font-family: "Inter";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("/static/console/fonts/inter.woff2") format("woff2");
}

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

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

body {
    margin: 0;
    font-family: var(--font);
    font-size: 16px;
    line-height: 1.5;
    color: var(--ink);
    background: var(--page);
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-strong); }

h1, h2, h3, h4 { margin: 0 0 .5rem; line-height: 1.25; font-weight: 650; }
h1 { font-size: 1.5rem; }
h2 { font-size: 1.2rem; }
h3 { font-size: 1.02rem; }
p { margin: 0 0 .75rem; }

/* Focus is never removed. A console driven from a keyboard on a busy pass is
   unusable without it. */
:focus-visible {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
    border-radius: 3px;
}

/* ------------------------------------------------------------------ layout */

.shell { display: flex; min-height: 100vh; align-items: stretch; }

.sidebar {
    flex: 0 0 240px;
    background: var(--card);
    border-right: 1px solid var(--line);
    padding: 1rem .75rem 2rem;
}

.brand {
    display: block;
    font-weight: 700;
    font-size: 1.05rem;
    letter-spacing: .01em;
    color: var(--ink);
    text-decoration: none;
    padding: .25rem .5rem 1rem;
}
.brand small { display: block; font-weight: 400; color: var(--ink-faint); font-size: .8rem; }

.nav-group { margin-bottom: 1.1rem; }
.nav-group > h4 {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .07em;
    color: var(--ink-faint);
    margin: 0 .5rem .3rem;
}
.nav-link {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: .5rem;
    padding: .45rem .5rem;
    border-radius: var(--radius);
    color: var(--ink);
    text-decoration: none;
}
.nav-link:hover { background: var(--line-soft); }
.nav-link[aria-current="page"] {
    background: var(--accent-wash);
    color: var(--accent-strong);
    font-weight: 600;
}

.main { flex: 1 1 auto; min-width: 0; padding: 1.25rem 1.5rem 4rem; }

.page-head {
    display: flex;
    flex-wrap: wrap;
    gap: var(--gap);
    align-items: flex-end;
    justify-content: space-between;
    margin-bottom: 1rem;
}
.page-head p { margin: 0; color: var(--ink-soft); max-width: 62ch; }

.scope-bar {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    align-items: center;
    padding: .5rem .75rem;
    margin-bottom: 1rem;
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    font-size: .9rem;
}
.scope-bar form { display: flex; gap: .4rem; align-items: center; margin: 0; }

/* ------------------------------------------------------------------- cards */

.card {
    background: var(--card);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    padding: 1rem;
    margin-bottom: 1rem;
    box-shadow: var(--shadow);
}
.card > h2:first-child, .card > h3:first-child { margin-top: 0; }
.card-note { color: var(--ink-soft); font-size: .9rem; }

.grid { display: grid; gap: var(--gap); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }

/* ------------------------------------------------------ the service board */

/* Read across a room. The figure is the screen; everything else supports it. */
.occupancy {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    align-items: flex-end;
}
.occupancy-figure {
    font-size: clamp(3rem, 10vw, 5.5rem);
    line-height: .95;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    letter-spacing: -.02em;
}
.occupancy-unit { font-size: .32em; font-weight: 600; color: var(--ink-soft); }
.occupancy-label {
    text-transform: uppercase;
    letter-spacing: .07em;
    font-size: .75rem;
    color: var(--ink-faint);
    margin-bottom: .35rem;
}
.occupancy-meter {
    height: 14px;
    background: var(--line-soft);
    border-radius: 7px;
    overflow: hidden;
    margin-top: .6rem;
}
.occupancy-meter > span { display: block; height: 100%; background: var(--accent); }
.occupancy-meter.is-full > span { background: var(--state-warn); }

.board-list { list-style: none; margin: 0; padding: 0; }
.board-list > li {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem 1rem;
    align-items: baseline;
    padding: .6rem .25rem;
    border-bottom: 1px solid var(--line-soft);
    font-size: 1.05rem;
}
.board-list > li:last-child { border-bottom: 0; }
.board-time {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
    font-size: 1.3rem;
    min-width: 4.2rem;
}
.board-party { font-weight: 600; }
.board-name { flex: 1 1 12rem; min-width: 0; }
.board-actions { display: flex; gap: .35rem; margin-left: auto; }

/* -------------------------------------------------------------- states */

.tag {
    display: inline-block;
    padding: .1rem .45rem;
    border-radius: 999px;
    font-size: .78rem;
    font-weight: 650;
    letter-spacing: .01em;
    white-space: nowrap;
    background: var(--state-idle-wash);
    color: var(--state-idle);
}
.tag-good { background: var(--state-good-wash); color: var(--state-good); }
.tag-warn { background: var(--state-warn-wash); color: var(--state-warn); }
.tag-bad  { background: var(--state-bad-wash);  color: var(--state-bad); }
.tag-accent { background: var(--accent-wash); color: var(--accent-strong); }

/* A provisional booking is the one state that must never read as confirmed
   (FR-09-006). It is given a stripe as well as a colour so it survives a
   monochrome screen and colour vision deficiency. */
.is-provisional {
    background-image: repeating-linear-gradient(
        135deg, transparent 0 8px, rgba(138, 88, 0, .09) 8px 16px);
}

.banner {
    border: 1px solid var(--line);
    border-left: 4px solid var(--state-idle);
    background: var(--card);
    border-radius: var(--radius);
    padding: .75rem 1rem;
    margin-bottom: 1rem;
}
.banner-good { border-left-color: var(--state-good); background: var(--state-good-wash); }
.banner-warn { border-left-color: var(--state-warn); background: var(--state-warn-wash); }
.banner-bad  { border-left-color: var(--state-bad);  background: var(--state-bad-wash); }
.banner p:last-child { margin-bottom: 0; }

/* -------------------------------------------------------------- tables */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.data {
    width: 100%;
    border-collapse: collapse;
    font-size: .94rem;
}
table.data th, table.data td {
    text-align: left;
    padding: .5rem .6rem;
    border-bottom: 1px solid var(--line-soft);
    vertical-align: top;
}
table.data th {
    font-size: .76rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--ink-faint);
    border-bottom: 1px solid var(--line);
    white-space: nowrap;
}
table.data tbody tr:hover { background: var(--line-soft); }
table.data td.num { font-variant-numeric: tabular-nums; text-align: right; }
.mono { font-family: var(--mono); font-size: .88em; }

/* --------------------------------------------------------------- forms */

label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: .2rem; }
.field { margin-bottom: .85rem; }
.field .helptext { display: block; font-size: .83rem; color: var(--ink-soft); margin-top: .2rem; }
.field .errorlist { margin: .2rem 0 0; padding-left: 1.1rem; color: var(--state-bad); font-size: .85rem; }

input[type=text], input[type=email], input[type=password], input[type=number],
input[type=date], input[type=time], input[type=datetime-local], input[type=search],
select, textarea {
    width: 100%;
    max-width: 34rem;
    padding: .45rem .55rem;
    font: inherit;
    color: var(--ink);
    background: #fff;
    border: 1px solid var(--line);
    border-radius: var(--radius);
}
textarea { max-width: 52rem; }
input[type=checkbox], input[type=radio] { width: auto; margin-right: .35rem; }

ul.checkbox-list { list-style: none; margin: 0; padding: 0; columns: 2; }
ul.checkbox-list label { font-weight: 400; }

.form-row { display: flex; flex-wrap: wrap; gap: var(--gap); align-items: flex-end; }
.form-row > .field { flex: 1 1 12rem; margin-bottom: 0; }

.button, button {
    display: inline-block;
    font: inherit;
    font-weight: 600;
    padding: .45rem .9rem;
    border-radius: var(--radius);
    border: 1px solid var(--line);
    background: #fff;
    color: var(--ink);
    cursor: pointer;
    text-decoration: none;
}
.button:hover, button:hover { background: var(--line-soft); }
/* One obvious primary action per screen. */
/*
 * The one primary control on a screen, in the Aimatric action colour. Every
 * other control is a link or an outlined button, which is what makes this one
 * read as the thing to press rather than as decoration.
 */
.button-primary, button.primary {
    background: var(--action);
    border-color: var(--action);
    color: #fff;
}
.button-primary:hover, button.primary:hover,
.button-primary:focus, button.primary:focus {
    background: var(--action-strong);
    border-color: var(--action-strong);
    color: #fff;
}
.button-danger, button.danger { color: var(--state-bad); border-color: var(--state-bad); }
.button-danger:hover, button.danger:hover { background: var(--state-bad-wash); }
.button-small, button.small { padding: .25rem .55rem; font-size: .85rem; }
button[disabled], .button[disabled] { opacity: .5; cursor: not-allowed; }

/*
 * Controls in a row sit on their bottom edge, not their centre. A submit
 * button next to a labelled input is taller than the input alone, and centring
 * the two leaves the button floating above the line the eye follows.
 */
.actions {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .5rem;
    margin-top: 1rem;
}
.actions .form-row { align-items: flex-end; }
.actions .button, .actions button { align-self: flex-end; }

/* --------------------------------------------------------- sign in page */

.centred {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
}
.centred .card { width: 100%; max-width: 25rem; }

/* ------------------------------------------------------------ transcript */

.turn {
    border-left: 3px solid var(--line);
    padding: .4rem 0 .4rem .75rem;
    margin-bottom: .5rem;
}
.turn-inbound { border-left-color: var(--accent); }
.turn-meta { font-size: .8rem; color: var(--ink-faint); display: flex; gap: .75rem; flex-wrap: wrap; }

.stage-bar { height: 8px; background: var(--line-soft); border-radius: 4px; overflow: hidden; }
.stage-bar > span { display: block; height: 100%; background: var(--accent); }
.stage-bar.breached > span { background: var(--state-bad); }

/* --------------------------------------------------------------- misc */

.muted { color: var(--ink-soft); }
.small { font-size: .87rem; }
.stack > * + * { margin-top: .75rem; }
.legend { display: grid; gap: .35rem; font-size: .87rem; }
.legend dt { font-weight: 700; }
.legend > div { display: flex; gap: .6rem; align-items: baseline; }

.empty {
    padding: 1.5rem;
    text-align: center;
    color: var(--ink-soft);
    border: 1px dashed var(--line);
    border-radius: var(--radius);
}

/* HTMX marks the element it is loading. A board that polls silently should not
   flicker, so only a deliberate request shows the indicator. */
.htmx-request .poll-dot { opacity: 1; }
.poll-dot {
    display: inline-block; width: .5rem; height: .5rem; border-radius: 50%;
    background: var(--accent); opacity: .25; transition: opacity .2s;
}

/* -------------------------------------------------------- narrow widths */

/* A tablet on a host stand. The board and the bookings list have to be usable
   here, which means the navigation stops taking a column and the board's cards
   stack rather than shrink. */
@media (max-width: 900px) {
    .shell { flex-direction: column; }
    .sidebar {
        flex: 0 0 auto;
        border-right: 0;
        border-bottom: 1px solid var(--line);
        padding: .5rem;
        display: flex;
        flex-wrap: wrap;
        gap: .25rem;
        align-items: center;
    }
    .brand { padding: .25rem .5rem; }
    .brand small { display: none; }
    .nav-group { margin: 0; display: flex; flex-wrap: wrap; gap: .25rem; }
    .nav-group > h4 { display: none; }
    .nav-link { padding: .35rem .55rem; font-size: .92rem; }
    .main { padding: 1rem .75rem 3rem; }
    .grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
    ul.checkbox-list { columns: 1; }

    /* The bookings list becomes one card per booking rather than a table that
       scrolls sideways: a host looking for one party should not have to swipe
       to find out whose it is. */
    table.responsive-cards thead { display: none; }
    table.responsive-cards, table.responsive-cards tbody,
    table.responsive-cards tr, table.responsive-cards td { display: block; width: 100%; }
    table.responsive-cards tr {
        border: 1px solid var(--line);
        border-radius: var(--radius);
        margin-bottom: .6rem;
        padding: .5rem .6rem;
        background: var(--card);
    }
    table.responsive-cards td { border: 0; padding: .15rem 0; }
    table.responsive-cards td::before {
        content: attr(data-label) " ";
        font-size: .74rem;
        text-transform: uppercase;
        letter-spacing: .05em;
        color: var(--ink-faint);
        margin-right: .4rem;
    }
    table.responsive-cards td.num { text-align: left; }
}

@media print {
    .sidebar, .actions, .scope-bar { display: none; }
    .card { box-shadow: none; break-inside: avoid; }
}


/* --------------------------------------------------------------------------
 * Aimatric brand chrome.
 * -------------------------------------------------------------------------- */

/*
 * The brand lockup: the AIMatric mark, then the product name.
 *
 * The mark alone rather than the full logo, because the wordmark beside
 * "AIMcom" read as "AIMatric AIMcom", one garbled phrase. The icon says whose
 * product this is without competing with the name that says which. It is the
 * company's mark, so it is used as supplied and never recoloured or stretched.
 */
.brand {
    display: flex;
    align-items: center;
    gap: .6rem;
    text-decoration: none;
}

.brand img {
    height: 26px;
    width: 26px;
    display: block;
    flex: none;
    border-radius: 5px;
}

.brand .brand-name {
    display: flex;
    align-items: center;
    font-size: 1.02rem;
    font-weight: 600;
    letter-spacing: -.01em;
}

/* The hairline. Disappears when the mark is missing, so the name stands alone
   rather than sitting behind a rule with nothing before it. */
.brand .brand-mark { color: var(--accent); }
.brand .brand-rest { color: var(--ink); }

/*
 * The one primary control per screen: take a booking, save, submit. Everything
 * else is a link or a secondary button, and the distinction is the point.
 */
.state-dot {
    display: inline-block;
    width: .5rem;
    height: .5rem;
    border-radius: 50%;
    background: var(--state-good-dot);
    margin-right: .35rem;
}
