/* ==========================================================================
   IsItOpn?  —  admin styles

   Loads on top of main.css and reuses its tokens, so light/dark and the
   contrast work already done there carry straight over.
   ========================================================================== */

body.admin {
    background: var(--page);
}

.admin-main {
    max-width: 1100px;
    margin: 0 auto;
    padding: 1rem 0.8rem 4rem;
}

/* --------------------------------------------------------------------------
   Top bar
   -------------------------------------------------------------------------- */
.admin-bar {
    background: var(--surface);
    border-bottom: 1px solid var(--rule);
    position: sticky;
    top: 0;
    z-index: 5;
}
.admin-bar-inner {
    max-width: 1100px;
    margin: 0 auto;
    padding: 0.6rem 0.8rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem 1rem;
}
.admin-brand {
    font-weight: 700;
    font-size: 1.1rem;
    text-decoration: none;
    color: var(--ink);
}
.admin-tag {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-muted);
    font-weight: 600;
}
.admin-nav {
    display: flex;
    flex-wrap: wrap;
    gap: 0.15rem 0.9rem;
    flex: 1 1 auto;
}
.admin-nav a {
    text-decoration: none;
    padding: 0.35em 0;
    font-size: 0.95rem;
}
.admin-nav a:hover { text-decoration: underline; }
.admin-nav a[aria-current="page"] {
    font-weight: 700;
    color: var(--ink);
    border-bottom: 2px solid var(--link);
}
.admin-user {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    font-size: 0.85rem;
    color: var(--ink-muted);
}
.admin-link { text-decoration: none; }
.admin-link:hover { text-decoration: underline; }
.role-tag {
    display: inline-block;
    font-size: 0.72rem;
    background: var(--surface-alt);
    border: 1px solid var(--rule);
    border-radius: 999px;
    padding: 0.05em 0.55em;
    margin-left: 0.2em;
}

/* --------------------------------------------------------------------------
   Panels
   -------------------------------------------------------------------------- */
.panel {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: 8px;
    padding: 1rem;
    margin-bottom: 1rem;
}
.panel h1 { font-size: 1.3rem; }
.panel h2 { font-size: 1.05rem; margin-top: 0; }
.panel h3 { font-size: 0.95rem; }

.panel-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.6rem;
    margin-bottom: 0.6rem;
}
.panel-head h1, .panel-head h2 { margin: 0; }

.panel.danger { border-color: var(--closed); }
.danger-button {
    background: var(--closed);
    color: #fff;
}
.danger-button:hover { background: var(--closed); opacity: 0.85; color: #fff; }

.help {
    font-size: 0.85rem;
    color: var(--ink-muted);
    margin: 0.3em 0 0.8em;
    max-width: 70ch;
}

.sticky-actions {
    position: sticky;
    bottom: 0.5rem;
    display: flex;
    gap: 0.6rem;
    box-shadow: 0 4px 18px rgb(0 0 0 / 0.14);
}

/* --------------------------------------------------------------------------
   Stats
   -------------------------------------------------------------------------- */
.stat-row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 0.7rem;
    margin: 0.8rem 0;
}
.stat {
    background: var(--surface-alt);
    border-radius: 6px;
    padding: 0.7rem;
}
.stat-n { display: block; font-size: 1.6rem; font-weight: 700; line-height: 1.1; }
.stat-l { display: block; font-size: 0.8rem; color: var(--ink-muted); }
.stat-alert { background: var(--notice-bg); }
.stat-alert .stat-n, .stat-alert .stat-l { color: var(--notice-ink); }

/* --------------------------------------------------------------------------
   Tables
   -------------------------------------------------------------------------- */
.admin-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.92rem;
}
.admin-table th, .admin-table td {
    text-align: left;
    padding: 0.55em 0.5em;
    border-bottom: 1px solid var(--rule);
    vertical-align: top;
}
.admin-table thead th {
    font-size: 0.78rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--ink-muted);
    border-bottom-width: 2px;
}
.admin-table tbody th { font-weight: 600; }
.admin-table.compact th, .admin-table.compact td { padding: 0.35em 0.5em; }
.admin-table .is-today th, .admin-table .is-today td { font-weight: 700; }
.admin-table td a + a { margin-left: 0.7em; }
.nowrap { white-space: nowrap; }

/* Tables scroll rather than forcing the page sideways on a phone. */
@media (max-width: 640px) {
    .panel { overflow-x: auto; }
}

.pill {
    display: inline-block;
    font-size: 0.72rem;
    font-weight: 600;
    border-radius: 999px;
    padding: 0.1em 0.6em;
    background: var(--surface-alt);
    border: 1px solid var(--rule);
    color: var(--ink-muted);
}
.pill-ok   { background: var(--ok-bg);     color: var(--ok-ink);     border-color: transparent; }
.pill-warn { background: var(--notice-bg); color: var(--notice-ink); border-color: transparent; }
.pill-off  { background: var(--err-bg);    color: var(--err-ink);    border-color: transparent; }

.report-details {
    margin: 0.3em 0 0;
    font-size: 0.9rem;
}

.tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 1rem;
    margin-bottom: 0.8rem;
    border-bottom: 1px solid var(--rule);
}
.tabs a {
    text-decoration: none;
    padding: 0.4em 0;
    font-size: 0.9rem;
}
.tabs a[aria-current="page"] {
    font-weight: 700;
    color: var(--ink);
    border-bottom: 2px solid var(--link);
}

/* --------------------------------------------------------------------------
   Forms
   -------------------------------------------------------------------------- */
.stacked fieldset, .hours-form fieldset {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 0.8rem;
    margin: 0 0 1rem;
}
legend {
    font-weight: 600;
    font-size: 0.9rem;
    padding: 0 0.4em;
}

.field { margin-bottom: 0.8rem; }
.field label, .label-like {
    display: block;
    font-size: 0.85rem;
    font-weight: 600;
    margin-bottom: 0.25em;
}
.field input, .field select, .field textarea { width: 100%; }
.field .help { margin: 0.3em 0 0; }

.field-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.7rem;
    align-items: flex-end;
}
.field-row .field { flex: 1 1 10rem; margin-bottom: 0.8rem; }
.field-row .field-narrow { flex: 0 1 7rem; }

.inline-form {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    align-items: center;
    margin-bottom: 0.8rem;
}

.checkbox {
    display: inline-flex;
    align-items: baseline;
    gap: 0.4em;
    font-size: 0.92rem;
    font-weight: 400;
    margin-bottom: 0.4em;
    cursor: pointer;
}
.checkbox input { width: auto; min-height: 0; }
.checkbox.tight { margin-bottom: 0; font-size: 0.85rem; }

.checkbox-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 0.2rem 0.8rem;
}

.form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.5rem;
}

/* Front-door map in the location editor. .map-frame comes from main.css — the
   frame is reused so the editor and the public page show the same thing at the
   same aspect ratio; only the height is trimmed to suit a form. */
.admin-map { margin-bottom: 0.8rem; }
.admin-map .map-frame { max-height: 22rem; }

/* Expanded by the ⤢ control, because 22rem of map is not much to pick one side
   of a building in. The whole block goes over the page rather than just the
   frame, so the status line and the off-site links come with it; the frame then
   takes whatever height is left instead of its own aspect ratio. */
.admin-map.is-expanded {
    position: fixed;
    inset: 0;
    z-index: 20;
    display: flex;
    flex-direction: column;
    margin: 0;
    padding: 0.8rem;
    background: var(--surface);
}
.admin-map.is-expanded .map-frame {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none;
    aspect-ratio: auto;
}
body.map-expanded { overflow: hidden; }
.map-empty {
    margin: 0;
    padding: 3rem 1rem;
    text-align: center;
    font-size: 0.9rem;
    color: var(--ink-muted);
}
.map-tools {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
}

/* The draggable map itself — .map-surface and everything under it — is in
   main.css, because tile-map.js draws the same map for the public location box.
   Only the frame around it is the editor's own. */

/* Reaching the weekly rota on a page that reads widest-layer-first. */
.jump-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.9rem;
    margin: 0;
    font-size: 0.85rem;
    color: var(--ink-muted);
}

.link-button {
    background: none;
    border: 0;
    color: var(--link);
    font: inherit;
    font-size: 0.85rem;
    padding: 0.2em 0;
    min-height: 0;
    cursor: pointer;
    text-decoration: underline;
}
.link-button:hover { background: none; color: var(--link-hover); }
.danger-link { color: var(--closed); }
.danger-link:hover { color: var(--closed); opacity: 0.8; }

@media (prefers-color-scheme: dark) {
    .link-button, .link-button:hover { color: var(--link); }
    .danger-link, .danger-link:hover { color: var(--closed); }
}

/* --------------------------------------------------------------------------
   Hours editor
   -------------------------------------------------------------------------- */
/* The five layers are groups inside one Opening hours panel rather than five
   panels of their own: at the top level they read as five separate subjects
   sitting alongside Details, which is what they are not. A rule down the left is
   enough to say "still hours" without another box inside a box. */
.hours-group {
    margin-top: 1.4rem;
    padding-left: 0.9rem;
    border-left: 3px solid var(--rule);
}
.hours-group > h3 {
    margin-top: 0;
    font-size: 1rem;
}
.hours-group:first-of-type { margin-top: 1rem; }

/* A heading with its own action beside it — the week preset on the weekly rota. */
.group-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}
.group-head h3 { margin: 0; }

@media (max-width: 40rem) {
    .hours-group {
        padding-left: 0.6rem;
        border-left-width: 2px;
    }
}

/* One pasted line, and the button that splits it up. */
.paste-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}
.paste-row input { flex: 1 1 18rem; }

.days {
    display: grid;
    gap: 0.7rem;
}
@media (min-width: 780px) {
    .days { grid-template-columns: 1fr 1fr; }
}

.day-panel {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 0.7rem;
    background: var(--surface-alt);
}
.day-head {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.4rem;
    margin-bottom: 0.4rem;
}
/* h4 since the weekly rota is now a group inside the hours panel rather than a
   panel of its own — the heading level moved down with it, the size did not. */
.day-head h4 {
    margin: 0;
    font-size: 0.95rem;
}
.day-actions { display: flex; gap: 0.8rem; }

.hours-rows { display: grid; gap: 0.4rem; }
.hours-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: 4px;
    padding: 0.4rem;
}
.hours-row input[type="time"] {
    min-height: 38px;
    padding: 0.3em 0.4em;
    flex: 0 1 auto;
    width: auto;
}
.hours-row .to { color: var(--ink-muted); font-size: 0.85rem; }

.closed-note {
    color: var(--ink-muted);
    font-size: 0.9rem;
    font-style: italic;
    margin: 0.2em 0;
}

.copy-panel { margin-top: 0.6rem; }
.copy-panel fieldset { margin-bottom: 0; background: var(--surface); }
.copy-days {
    display: flex;
    flex-wrap: wrap;
    gap: 0.2rem 0.7rem;
    margin-bottom: 0.5rem;
}
.copy-shortcuts {
    display: flex;
    flex-wrap: wrap;
    gap: 0.8rem;
    margin-bottom: 0.6rem;
}
.copy-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.6rem;
}
.copy-status {
    font-size: 0.82rem;
    color: var(--ok-ink);
}

/* A wide screen has room for a whole day on one line — day name, the hours
   themselves, then the day's actions — so the week reads as seven rows rather
   than two columns of stacked panels. `display: contents` promotes the head's
   two children into the panel's own flex row, which is what lets the day name
   sit before the hours and the actions after them without moving any markup.
   It has to come after the rules it overrides: a media query adds no
   specificity, so a plain `.day-head` further down the file would win. */
@media (min-width: 1000px) {
    .days { grid-template-columns: 1fr; gap: 0.45rem; }

    .day-panel {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 0.5rem 0.9rem;
        padding: 0.45rem 0.7rem;
    }
    .day-head {
        display: contents;
        margin-bottom: 0;
    }
    .day-head h3 {
        order: 1;
        flex: 0 0 7rem;
        margin: 0;
    }
    .day-panel .hours-rows {
        order: 2;
        flex: 1 1 auto;
    }
    .day-panel .hours-row {
        border: 0;
        background: none;
        padding: 0;
        flex-wrap: nowrap;
    }
    .day-panel .closed-note { margin: 0; }
    .day-actions {
        order: 3;
        flex: 0 0 auto;
        margin-left: auto;
    }
    .copy-panel {
        order: 4;
        flex: 1 0 100%;
        margin-top: 0.2rem;
    }
}

.repeat-list { display: grid; gap: 0.7rem; margin-bottom: 0.7rem; }
.repeat-item {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 0.7rem;
    background: var(--surface-alt);
}
.repeat-item .field-row:last-child { margin-bottom: 0; }
.repeat-item .field-row .field { margin-bottom: 0.5rem; }

.inline-fieldset {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.2rem 0.7rem;
    margin-bottom: 0.6rem !important;
    padding: 0.5rem 0.7rem !important;
    background: var(--surface);
}
.inline-fieldset legend { font-size: 0.82rem; }

.ex-hours { margin: 0.5rem 0; }

.repeat-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.4rem;
    align-items: center;
}
.repeat-row select { flex: 0 1 9rem; }
.repeat-row input { flex: 1 1 12rem; }

/* --------------------------------------------------------------------------
   Counters and services — a whole week nested inside one repeat item
   -------------------------------------------------------------------------- */
/* Seven lines, not seven panels: a counter's week sits inside a card that is
   itself one of several, so it has to stay quiet enough to read past. Each day
   is a fixed name column, the hours, then the one control that adds to it —
   which keeps the time boxes on a shared left edge down all seven days. */
.svc-week {
    display: grid;
    gap: 0.35rem;
    margin: 0.6rem 0;
    padding: 0.5rem 0.6rem;
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: 6px;
}
.svc-day {
    display: grid;
    grid-template-columns: 3rem minmax(0, 1fr) auto;
    align-items: start;
    gap: 0.3rem 0.7rem;
}
.svc-day-name {
    font-size: 0.85rem;
    font-weight: 600;
    padding-top: 0.35em;
}
.svc-day-rows { display: grid; gap: 0.35rem; }
.svc-day-rows .hours-row {
    border: 0;
    background: none;
    padding: 0;
}
.svc-day-rows .closed-note { margin: 0.35em 0; }
.svc-day-actions {
    display: flex;
    gap: 0.7rem;
    justify-self: end;
    white-space: nowrap;
}

/* The copy panel is cloned into the day it was opened from, so it has to break
   out of the three columns the day is laid out in. */
.svc-day .day-copy {
    grid-column: 1 / -1;
    margin-top: 0.2rem;
}

/* The status line under the heading: what each counter resolved to when it was
   last saved, which is the one thing its own grid cannot show. */
.service-status-list {
    margin: 0 0 0.8rem;
    font-size: 0.9rem;
}

/* Below this the three columns stop fitting a time pair, a tick and a remove
   link, so the day name takes a line of its own and the hours run full width. */
@media (max-width: 40rem) {
    .svc-day {
        grid-template-columns: 1fr auto;
    }
    .svc-day-name {
        grid-column: 1 / -1;
        padding-top: 0;
    }
}

/* --------------------------------------------------------------------------
   Categories editor
   -------------------------------------------------------------------------- */
/* Columns rather than a flex row: only the slug carries a note under it, and
   under .field-row's bottom alignment that one note lifted the slug box a line
   above every other box in the row. The card is three shared lines instead —
   label, control, note — so a note under one field cannot move another. */
.category-fields {
    display: grid;
    grid-template-columns: minmax(9rem, 1.3fr) minmax(11rem, 1.7fr) 5rem minmax(6rem, auto);
    grid-template-rows: auto auto auto;
    gap: 0.25rem 0.8rem;
    align-items: start;
}
.category-fields .field {
    display: grid;
    grid-row: 1 / -1;
    grid-template-rows: subgrid;
    align-content: start;
    margin-bottom: 0;
    min-width: 0;
}
/* The rows carry the spacing now, so the margins that stood in for them go. */
.category-fields .field > label { margin-bottom: 0; }
.category-fields .field .help { margin: 0; }

/* Not a control, but it reads as the answer to the label above it, so it sits
   on the control's line rather than at the top of a line-and-a-half-tall row. */
.category-usage {
    align-self: center;
    margin: 0;
}

/* What the row is, above; what to do with it, below a hairline. Loose beside
   the fields, the tick and the button read as a footer once they are ruled off. */
.category-item .item-footer {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-top: 0.7rem;
    padding-top: 0.6rem;
    border-top: 1px solid var(--rule);
}
.category-item .item-footer .checkbox { margin: 0; }

/* Four columns will not hold a name, a slug and a URL under it on a phone. The
   two text fields take the full width each; the number and its count pair up. */
@media (max-width: 46rem) {
    .category-fields {
        grid-template-columns: 5rem minmax(6rem, 1fr);
        grid-template-rows: none;
        gap: 0.6rem 0.8rem;
    }
    .category-fields .field {
        display: block;
        grid-row: auto;
        grid-template-rows: none;
    }
    .category-fields .field:nth-child(-n+2) { grid-column: 1 / -1; }
    .category-fields .field > label { margin-bottom: 0.25em; }
    .category-fields .field .help { margin: 0.3em 0 0; }
    .category-usage { align-self: auto; }
}

/* --------------------------------------------------------------------------
   Bulk editor
   -------------------------------------------------------------------------- */
.bulk-search { align-items: flex-end; }
.bulk-search .field { margin-bottom: 0; }

.tick-col { width: 2.2rem; }
.tick-col .checkbox { margin: 0; }

/* Two or three fields abreast on a wide screen, one on a phone: each is a
   checkbox that arms the control beneath it, so they have to stay paired. */
.bulk-fields {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 0.7rem 1rem;
}
.bulk-field {
    border: 1px solid var(--rule);
    border-radius: 6px;
    padding: 0.6rem;
    background: var(--surface-alt);
}
.bulk-field .checkbox { font-weight: 600; margin-bottom: 0.35em; }
.bulk-field .bulk-control input,
.bulk-field .bulk-control select,
.bulk-field .bulk-control textarea { width: 100%; }
.bulk-field .help { margin: 0.4em 0 0; }

/* --------------------------------------------------------------------------
   Activity log
   -------------------------------------------------------------------------- */
.audit-filter {
    align-items: flex-end;
    margin-bottom: 1rem;
}
.audit-filter .field { margin-bottom: 0; }

/* A date input carries its own picker and placeholder, so it will not shrink
   to the width .field-narrow allows without clipping them. */
.audit-filter .field-date { flex: 0 1 10.5rem; }

.audit-filter .filter-actions {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.7rem;
}

/* The linked record and the free-text detail are two separate facts about an
   entry — stacked, they stay legible where a bulk edit lists eighty ids. */
.audit-target { display: block; }
.audit-detail { display: block; }
.audit-target + .audit-detail { margin-top: 0.15em; }

/* The id qualifies the name beside it rather than competing with it: quieter
   than the name, and outside the link so what is clickable stays the record. */
.record-id {
    color: var(--ink-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Login
   -------------------------------------------------------------------------- */
body.admin-plain {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 1rem;
}
.login-card {
    background: var(--surface);
    border: 1px solid var(--rule);
    border-radius: 10px;
    padding: 1.6rem;
    width: 100%;
    max-width: 22rem;
}
.login-card h1 { margin-bottom: 0.1em; }
.login-card .field { margin-bottom: 1rem; }
.login-card button { width: 100%; }
.login-card .back { margin-top: 1rem; font-size: 0.85rem; }
