/* DO Forecast (oxy_forecast.js, oxy_farm_view.js). Every rule sits under .oxy-ui: the side-panel section's root,
   the farm view's map panes and its player bar (tests/frontend/oxy_app_hooks.test.js guards it). */

/* The section is one card in the farm card's glass (.oxy-farm-card), edge to edge, as the Ocean stations box under
   it (ocean_stations.css): a row per farm, a red or amber one marked by a glowing bar on its left edge. No drop
   shadow, as the date card has none: the left panel scrolls, so it would clip one to a faint box behind them all. */
.oxy-ui#oxy_container {
    padding: 0;
    overflow: hidden;
    border-radius: 14px;
    background: var(--bc-glass-bg);
    -webkit-backdrop-filter: var(--bc-glass-blur);
    backdrop-filter: var(--bc-glass-blur);
    border: var(--bc-glass-border);
    box-shadow: var(--bc-glass-edge);
}
.oxy-ui#oxy_container .panel-empty-state { padding: 14px 16px; font-size: 12px; color: rgba(226, 232, 240, 0.6); }

/* A farm's row: its name (Oxanium, as the farm card's title) and status pill, its verdict, its days. */
.oxy-ui .oxy-card {
    position: relative;
    gap: 4px;
    margin: 0;
    padding: 13px 16px 14px;
    transition: background-color 0.15s ease;
}
.oxy-ui .oxy-card + .oxy-card { border-top: 1px solid rgba(148, 163, 184, 0.12); }
.oxy-ui .oxy-card:hover { background: rgba(96, 165, 250, 0.08); }
.oxy-ui .oxy-card.oxy-red::before,
.oxy-ui .oxy-card.oxy-amber::before {
    content: "";
    position: absolute;
    left: 0;
    top: 12px;
    bottom: 12px;
    width: 3px;
    border-radius: 0 2px 2px 0;
    background: #ef4444;
    box-shadow: 0 0 12px rgba(239, 68, 68, 0.7);
}
.oxy-ui .oxy-card.oxy-amber::before { background: #facc15; box-shadow: 0 0 12px rgba(250, 204, 21, 0.6); }
.oxy-ui .oxy-card-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.oxy-ui .oxy-card-name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: Oxanium, sans-serif;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.3px;
    line-height: 1.2;
    color: #f8fafc;
}

/* A quiet pill in the brand's blue: a farm card's "Dissolved Oxygen" (.oxy-card-topic, what it forecasts, never
   coloured by status: the card's edge, verdict and days say that) and a pen's status (.oxy-pen-status) alike; a pen's
   Critical and Warning (.oxy-red, .oxy-amber on it) in the grid key's red and amber, deepened for their white text. */
.oxy-ui .oxy-chip,
.oxy-ui .oxy-pen-status {
    flex: 0 0 auto;
    padding: 3px 10px 4px;
    border-radius: 999px;
    background: rgba(46, 142, 255, 0.16);
    box-shadow: inset 0 0 0 1px rgba(96, 165, 250, 0.28);
    color: #bfdbfe;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.3px;
    line-height: 1.2;
}
.oxy-ui .oxy-pen-status.oxy-red,
.oxy-ui .oxy-pen-status.oxy-amber { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22); color: #f8fafc; }
.oxy-ui .oxy-pen-status.oxy-red { background: #b91c1c; }
.oxy-ui .oxy-pen-status.oxy-amber { background: #8f6d15; }

.oxy-ui .oxy-verdict {
    font-size: 12px;
    font-weight: 500;
    line-height: 1.45;
    color: rgba(226, 232, 240, 0.8);
}

/* The farm's forecast days: a bar each, in its lowest DO's status colour (red and amber glowing; healthy the brand's
   blue, quiet), over its initial; the day shown's initial white and its bar ringed, the days before it dim. */
.oxy-ui .oxy-days { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); gap: 3px; margin-top: 7px !important; }
.oxy-ui .oxy-days:empty { display: none; }
.oxy-ui .oxy-day {   /* a button: none of app.css's global button (navy fill, padding) */
    display: grid;
    justify-items: center;
    gap: 5px;
    min-width: 0;
    padding: 3px 0 2px;
    margin: -3px 0 -2px;
    border: 0;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
    overflow: visible;
    isolation: auto;
}
.oxy-ui .oxy-day:focus-visible { outline: 2px solid #2e8eff; outline-offset: 1px; }
@media (hover: hover) {
    .oxy-ui .oxy-day:hover { opacity: 1; }
    .oxy-ui .oxy-day:hover .oxy-day-wd { color: #f8fafc; }
    .oxy-ui .oxy-day:hover .oxy-day-bar { filter: brightness(1.3); }
}
.oxy-ui .oxy-day-bar { width: 100%; height: 5px; border-radius: 3px; background: rgba(46, 142, 255, 0.5); }
.oxy-ui .oxy-day.is-amber .oxy-day-bar { background: #fbbf24; box-shadow: 0 0 8px rgba(251, 191, 36, 0.45); }
.oxy-ui .oxy-day.is-red .oxy-day-bar { background: #ef4444; box-shadow: 0 0 8px rgba(239, 68, 68, 0.55); }
.oxy-ui .oxy-day.is-none .oxy-day-bar { background: rgba(148, 163, 184, 0.2); }
.oxy-ui .oxy-day-wd { font-size: 9px; font-weight: 700; line-height: 1; color: rgba(203, 213, 225, 0.45); }
.oxy-ui .oxy-day.is-before { opacity: 0.35; }
.oxy-ui .oxy-day.is-shown .oxy-day-wd { color: #f8fafc; }
.oxy-ui .oxy-day.is-shown .oxy-day-bar { outline: 1px solid rgba(248, 250, 252, 0.75); outline-offset: 1px; }

/* ── The farm on the main map (oxy_farm_view.js): its panes carry .oxy-ui. ─────────────────────── */
.oxy-ui .oxy-field { pointer-events: none; }

/* Pen labels (permanent Leaflet tooltips, centred on the pen). */
.oxy-ui .leaflet-tooltip.oxy-pen-label {
    padding: 0 4px;
    border: 0;
    border-radius: 4px;
    background: rgba(2, 6, 23, 0.65);
    box-shadow: none;
    color: #f1f5f9;
    font-size: 11px;
    font-weight: 700;
    line-height: 15px;
    font-variant-numeric: tabular-nums;
}
.oxy-ui .leaflet-tooltip.oxy-pen-label::before { display: none; }
.oxy-ui .leaflet-tooltip.oxy-pen-label.oxy-red { background: #dc2626; color: #ffffff; }
.oxy-ui .leaflet-tooltip.oxy-pen-label.oxy-amber { background: #fbbf24; color: #0f172a; }

/* ── The bar and the farm card share one glass: the portal's frosted glass (app.css --bc-glass-*), with a shadow
   as they float over the map. */
.oxy-ui.oxy-player,
.oxy-ui.oxy-farm-card {
    border-radius: 18px;
    background: var(--bc-glass-bg);
    -webkit-backdrop-filter: var(--bc-glass-blur);
    backdrop-filter: var(--bc-glass-blur);
    border: var(--bc-glass-border);
    box-shadow: var(--bc-glass-edge), 0 18px 44px rgba(0, 8, 22, 0.55);
    color: #e2e8f0;
}

/* ── The player bar (tpl-oxy-player), docked at the bottom centre of the map. On a desktop it stays clear of both
   side panels (app.css .side-panel: 16 px in, 290 px wide), and so of the map's corner controls too. Its first row is
   a fixed height, so the lowest pen's reading, which arrives after the flight is aimed, never moves the bar. */
.oxy-ui.oxy-player {
    position: fixed;
    left: 50%;
    bottom: 20px;
    z-index: 1000;
    transform: translateX(-50%);
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-rows: 22px auto auto;
    grid-template-areas: "play time low close" "play scrub scrub scrub" "play days days days";
    align-items: center;
    column-gap: 14px;
    row-gap: 7px;
    width: max-content;
    max-width: max(calc(100vw - 2 * (16px + 290px + 24px)), 360px);
    padding: 9px 12px 11px 14px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}
.oxy-ui.oxy-player.is-shown { opacity: 1; visibility: visible; transition: opacity 0.25s ease; }

/* The bar's buttons: none of app.css's global button (navy fill, padding). */
.oxy-ui .oxy-player-play,
.oxy-ui .oxy-player-close {
    display: grid;
    place-items: center;
    padding: 0;
    border-radius: 50%;
    overflow: visible;
    isolation: auto;
    transition: background-color 0.15s ease, color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}
.oxy-ui .oxy-player-play:focus-visible,
.oxy-ui .oxy-player-close:focus-visible,
.oxy-ui .oxy-player-day:focus-visible { outline: 2px solid #2e8eff; outline-offset: 2px; }

/* Play / pause: the brand blue disc; the bar's .is-playing shows the pause icon. */
.oxy-ui .oxy-player-play {
    grid-area: play;
    width: 46px;
    height: 46px;
    background: radial-gradient(circle at 50% 30%, #5aa8ff, #2e8eff 60%, #1f6fd6);
    color: #ffffff;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 0 0 6px rgba(46, 142, 255, 0.12), 0 6px 22px rgba(46, 142, 255, 0.45);
}
.oxy-ui .oxy-player-play:hover:not(:disabled) { background: radial-gradient(circle at 50% 30%, #74b6ff, #4b9dff 60%, #2e8eff); color: #ffffff; }
.oxy-ui .oxy-player-play:active { transform: scale(0.94); }
.oxy-ui .oxy-player-play:disabled {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(226, 232, 240, 0.35);
    box-shadow: none;
    transform: none;
    cursor: default;
}
.oxy-ui .oxy-player-play svg { width: 22px; height: 22px; fill: currentColor; }
.oxy-ui.oxy-player .oxy-icon-pause,
.oxy-ui.oxy-player.is-playing .oxy-icon-play { display: none; }
.oxy-ui.oxy-player.is-playing .oxy-icon-pause { display: block; }

.oxy-ui .oxy-player-close {   /* as the cards' icon buttons (.oxy-fc-toggle): a quiet 28 px square, 8 px corners; its ✕ kept */
    grid-area: close;
    justify-self: end;
    width: 28px;
    height: 28px;
    margin: -2px -4px -2px 0;
    border-radius: 8px;
    background: transparent;
    color: rgba(226, 232, 240, 0.65);
}
.oxy-ui .oxy-player-close:hover { background: rgba(255, 255, 255, 0.1); color: #ffffff; }
.oxy-ui .oxy-player-close svg { width: 13px; height: 13px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }

/* The moment shown, and the lowest pen then (its reading in white on a pill of its colour, --c from JS, as the grid's
   cells), over the bars: the time, "lowest" and the pen's name all in one type, the pen name's (12 px, bold, one line
   height), each in its own colour. */
.oxy-ui .oxy-player-time {
    grid-area: time;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
    color: #f8fafc;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.oxy-ui .oxy-player-time:empty { display: none; }
.oxy-ui .oxy-player-low {
    grid-area: low;
    justify-self: end;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
    color: rgba(203, 213, 225, 0.6);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}
.oxy-ui .oxy-player-low b { font-weight: inherit; color: #e2e8f0; }
.oxy-ui .oxy-player-low-v {
    padding: 2px 8px;
    border-radius: 999px;
    background: rgb(var(--c, 51, 65, 85));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
    color: #f8fafc;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
}
.oxy-ui .oxy-player-note {
    grid-area: scrub;
    display: none;
    font-size: 12px;
    color: #cbd5e1;
}
.oxy-ui.oxy-player.is-off .oxy-player-note { display: block; }
.oxy-ui.oxy-player.is-off .oxy-player-track { display: none; }

/* The bars (oxy_farm_view.js bars()): the farm's lowest DO each hour of the run to come, as the dial's bars (up from
   the floor, longer for more DO, in its status colour: the brand blue, amber, red), the hour shown lit; the threshold
   dashed across them in red, midnights as faint rules, and a dot on the lit bar's top. Their box spans the thumb's
   travel (7 px in from each end), so bars, thumb and dot agree. */
.oxy-ui .oxy-player-track {
    grid-area: scrub;
    position: relative;
    height: 42px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(2, 10, 24, 0.2), rgba(2, 10, 24, 0.55));
    box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.1);
}
.oxy-ui .oxy-bars { position: absolute; top: 0; left: 7px; width: calc(100% - 14px); height: 100%; overflow: visible; pointer-events: none; z-index: 0; }
/* The hours already played, dimmed (as the dial dims the hours gone): a veil from the bars' start to the thumb. */
.oxy-ui .oxy-player-track::after {
    content: "";
    position: absolute;
    left: 7px;
    top: 0;
    bottom: 0;
    width: calc(var(--p, 0) / 100 * (100% - 14px));
    background: rgba(3, 15, 32, 0.5);
    pointer-events: none;
    z-index: 1;
}
.oxy-ui .oxy-bar { opacity: 0.72; }
.oxy-ui .oxy-bar.is-now { opacity: 1; filter: brightness(1.25); }
.oxy-ui .oxy-bars-thr { stroke: rgba(248, 113, 113, 0.85); stroke-width: 1; stroke-dasharray: 3 4; vector-effect: non-scaling-stroke; }
.oxy-ui .oxy-bars-thr-label {
    position: absolute;
    z-index: 3;
    right: 10px;
    transform: translateY(-115%);   /* over the line, clear of the bars' tops at its height */
    padding: 0 3px;
    border-radius: 3px;
    background: rgba(2, 10, 24, 0.7);
    font-size: 9px;
    font-weight: 700;
    line-height: 1.3;
    color: rgba(252, 165, 165, 0.95);
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}
.oxy-ui .oxy-bars-dot {
    position: absolute;
    z-index: 3;
    left: calc(7px + var(--p, 0) / 100 * (100% - 14px));
    top: calc(var(--y, 50) * 1%);
    width: 10px;
    height: 10px;
    margin: -5px 0 0 -5px;
    border-radius: 50%;
    background: #ffffff;
    box-shadow: 0 0 0 3px rgba(46, 142, 255, 0.5), 0 0 14px rgba(147, 197, 253, 0.9);
    pointer-events: none;
}
.oxy-ui .oxy-player-scrub:disabled ~ .oxy-bars-dot { opacity: 0.4; }
.oxy-ui .oxy-player-scrub:focus-visible ~ .oxy-bars-dot { box-shadow: 0 0 0 2px #001629, 0 0 0 4px #2e8eff; }

/* The native range over the bars: a clear track carrying the midnight rules (--ticks), and a thumb that is a white
   hairline the track's height (the dot marks the reading). The thumb's centre travels from 7 px in to 7 px from the end. */
.oxy-ui .oxy-player-scrub {
    --notch: rgba(255, 255, 255, 0.16);
    -webkit-appearance: none;
    appearance: none;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    background: transparent;
    cursor: pointer;
    z-index: 2;
}
.oxy-ui .oxy-player-scrub:focus { outline: none; }
.oxy-ui .oxy-player-scrub:disabled { cursor: default; }
.oxy-ui .oxy-player-scrub::-webkit-slider-runnable-track { height: 100%; border-radius: 10px; background: var(--ticks, none); }
.oxy-ui .oxy-player-scrub::-moz-range-track { height: 100%; border-radius: 10px; background: var(--ticks, none); }
.oxy-ui .oxy-player-scrub::-moz-range-progress { background: transparent; }
.oxy-ui .oxy-player-scrub::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 100%;
    border: 0;
    border-radius: 0;
    background: linear-gradient(90deg, transparent 6.25px, rgba(255, 255, 255, 0.85) 6.25px 7.75px, transparent 7.75px);
    box-shadow: none;
}
.oxy-ui .oxy-player-scrub::-moz-range-thumb {
    width: 14px;
    height: 100%;
    border: 0;
    border-radius: 0;
    background: linear-gradient(90deg, transparent 6.25px, rgba(255, 255, 255, 0.85) 6.25px 7.75px, transparent 7.75px);
    box-shadow: none;
}
.oxy-ui .oxy-player-scrub:disabled::-webkit-slider-thumb { opacity: 0.35; }
.oxy-ui .oxy-player-scrub:disabled::-moz-range-thumb { opacity: 0.35; }

/* The day chips: quiet glass, each with its day's lowest DO in white on a pill of its colour (--c, as the grid's). The
   day playing is lit in the brand's blue (a chip jumps the player to its day, which then plays on); hover lifts a chip
   to say it can be clicked. */
.oxy-ui .oxy-player-days {
    grid-area: days;
    display: flex;
    gap: 5px;
    min-width: 0;
    padding: 6px 5px 8px;   /* room for a lifted chip and the underline, which overflow would clip */
    margin: -6px -5px -8px;
    overflow-x: auto;
    scrollbar-width: none;
}
.oxy-ui .oxy-player-days::-webkit-scrollbar { display: none; }
.oxy-ui .oxy-player-day {
    position: relative;
    flex: 1 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    padding: 4px 4px 4px 9px;
    border-radius: 999px;
    overflow: visible;
    isolation: auto;
    background: rgba(255, 255, 255, 0.04);
    color: rgba(226, 232, 240, 0.78);
    font-size: 11px;
    line-height: 1.1;
    box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.16);
    transition: transform 0.15s ease, opacity 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
}
.oxy-ui .oxy-player-day-name {   /* the pill's line and padding, so the day and its DO share a baseline */
    padding: 2px 0;
    font-size: 12px;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.3px;
    white-space: nowrap;
}
.oxy-ui .oxy-player-day-min {
    min-width: 32px;
    padding: 2px 6px;
    border-radius: 999px;
    background: rgb(var(--c, 51, 65, 85));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22);
    color: #f8fafc;
    font-size: 12px;
    font-weight: 700;
    line-height: 1.2;
    text-align: center;
    font-variant-numeric: tabular-nums;
}
@supports (text-box: trim-both cap alphabetic) {   /* the line cut to the digits, so they sit in the pill's middle */
    .oxy-ui .oxy-player-day-name,
    .oxy-ui .oxy-player-day-min,
    .oxy-ui .oxy-player-low-v { padding-top: 5px; padding-bottom: 5px; text-box: trim-both cap alphabetic; }
}
@media (hover: hover) {   /* a tap mustn't leave a chip lifted */
    .oxy-ui .oxy-player-day:hover { transform: translateY(-2px); background: rgba(255, 255, 255, 0.08); color: #ffffff; }
}
.oxy-ui .oxy-player-day.is-playing {
    background: rgba(46, 142, 255, 0.22);
    color: #ffffff;
    box-shadow: inset 0 0 0 1.5px #60a5fa, 0 0 18px rgba(46, 142, 255, 0.35);
}

/* ── The farm card (tpl-oxy-farm-card), on the right of the map: the bar's glass, beside the right panel (--right)
   and clear of the bar (--below), both set from JS. Its own scroll when the window is short. */
.oxy-ui.oxy-farm-card {
    position: fixed;
    top: 100px;
    right: var(--right, 16px);
    z-index: 1000;
    width: 336px;
    max-height: calc(100vh - 100px - var(--below, 160px));
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    scrollbar-color: rgba(255, 255, 255, 0.15) transparent;
    padding: 16px 16px 18px;
}

/* Its buttons: none of app.css's global button (navy fill, padding).
   :where() keeps this reset above app.css's and below each button's own rules here. */
.oxy-ui.oxy-farm-card :where(button) {
    padding: 0;
    overflow: visible;
    isolation: auto;
    font: inherit;
    line-height: 1;
}
.oxy-ui.oxy-farm-card :where(button) span:first-child { transition: none; }
.oxy-ui.oxy-farm-card :where(button):focus-visible { outline: 2px solid #2e8eff; outline-offset: 2px; }

/* The header: as the side-panel card, larger, ruled off from the pens; red or amber marks the card's left edge, as it
   does the card's, and glows. */
.oxy-ui .oxy-fc-head { position: relative; padding-bottom: 14px; border-bottom: 1px solid rgba(148, 163, 184, 0.14); }
.oxy-ui .oxy-fc-head.oxy-red::before,
.oxy-ui .oxy-fc-head.oxy-amber::before {
    content: "";
    position: absolute;
    left: -17px;
    top: 2px;
    bottom: 16px;
    width: 3px;
    border-radius: 0 2px 2px 0;
    background: #ef4444;
    box-shadow: 0 0 12px rgba(239, 68, 68, 0.7);
}
.oxy-ui .oxy-fc-head.oxy-amber::before { background: #facc15; box-shadow: 0 0 12px rgba(250, 204, 21, 0.6); }
.oxy-ui.oxy-farm-card.is-collapsed .oxy-fc-head { padding-bottom: 0; border-bottom: 0; }   /* folded: nothing under it to rule off */
.oxy-ui.oxy-farm-card.is-collapsed .oxy-fc-head::before { bottom: 2px; }
.oxy-ui .oxy-fc-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.oxy-ui .oxy-fc-name {   /* the size of the side panel's farm names (.oxy-card-name) */
    margin: 0;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: Oxanium, sans-serif;
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 0.3px;
    line-height: 1.2;
    color: #f8fafc;
}
/* The card's icon buttons, as the date card's collapse chevron (app.css .date-display .left-panel-toggle): a quiet
   28 px square, 8 px corners, a double chevron (fold up, back left); hover lights it. Folded, the fold chevron turns down. */
.oxy-ui .oxy-fc-toggle,
.oxy-ui .oxy-pen-back {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    width: 28px;
    height: 28px;
    border-radius: 8px;
    background: transparent;
    color: rgba(226, 232, 240, 0.65);
    transition: background-color 0.15s ease, color 0.15s ease;
}
.oxy-ui .oxy-fc-toggle { margin: -4px -6px -4px auto; }
.oxy-ui .oxy-fc-toggle:hover,
.oxy-ui .oxy-pen-back:hover { background: rgba(255, 255, 255, 0.1); color: #ffffff; }
.oxy-ui .oxy-fc-toggle i,
.oxy-ui .oxy-pen-back i { font-size: 13px; line-height: 1; }
.oxy-ui .oxy-fc-toggle i { transition: transform 0.2s ease; }
.oxy-ui.oxy-farm-card.is-collapsed .oxy-fc-toggle i { transform: rotate(180deg); }
.oxy-ui .oxy-fc-head .oxy-verdict { margin: 6px 0 0; font-size: 12.5px; line-height: 1.45; color: #e2e8f0; }
.oxy-ui .oxy-fc-meta {
    margin: 2px 0 0;
    font-size: 11px;
    color: rgba(203, 213, 225, 0.6);
}
.oxy-ui.oxy-farm-card.is-collapsed .oxy-fc-body { display: none; }
/* The farm's name and "Forecast" (no status chip: the header's edge marks red or amber), on one line in both views:
   fitName() takes its font down as far as it must to fit. A pen open, the header is only that; its verdict and
   forecast details fold away, so the pen has the card. !important: jQuery's toggles (header()) show them with an
   inline display. */
.oxy-ui.oxy-farm-card.is-pen .oxy-fc-head .oxy-verdict,
.oxy-ui.oxy-farm-card.is-pen .oxy-fc-meta { display: none !important; }
.oxy-ui.oxy-farm-card.is-pen .oxy-fc-head { padding-bottom: 10px; }

.oxy-ui .oxy-fc-label {
    margin: 12px 0 8px;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.4px;
    line-height: 1.2;
    color: rgba(255, 255, 255, 0.71);
}

/* The pen × day grid: each pen's lowest DO per day, all in muted grey but where it matters, in the field's colour for
   it deepened for white text (--c): any day's in warning or worse (.is-alert), and the day shown's lowest (.is-low).
   Columns are the player's chips; the farm's lines (N, S) sit apart, as on the map. */
.oxy-ui .oxy-grid {
    display: grid;
    grid-template-columns: minmax(22px, max-content) repeat(var(--days, 9), minmax(0, 1fr));
    gap: 3px;
    align-items: center;
}
.oxy-ui .oxy-grid-day {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 3px 0 4px;
    border-radius: 6px;
    font-size: 10px;
    line-height: 1.2;
    color: rgba(226, 232, 240, 0.55);
    white-space: nowrap;
    transition: background-color 0.2s ease, color 0.2s ease;
}
.oxy-ui .oxy-grid-day .js-d { font-size: 11px; font-weight: 600; color: rgba(226, 232, 240, 0.85); font-variant-numeric: tabular-nums; }
.oxy-ui .oxy-grid-day.is-playing { background: rgba(226, 232, 240, 0.1); color: rgba(241, 245, 249, 0.85); }   /* the day shown: lit, not coloured */
.oxy-ui .oxy-grid-day.is-playing .js-d { color: #f8fafc; }
.oxy-ui .oxy-grid-pen {
    margin-left: -4px;
    padding: 2px 4px;
    border-radius: 4px;
    font-size: 11px;
    font-weight: 800;
    line-height: 1.2;
    color: rgba(226, 232, 240, 0.6);
    transition: color 0.12s ease, background-color 0.12s ease;
}
.oxy-ui .oxy-grid-pen.is-hover { color: #0f172a; background: #ffffff; }   /* the pen lit on the map */
.oxy-ui .oxy-grid-cell {
    position: relative;
    height: 22px;
    min-width: 0;
    border-radius: 6px;
    background: rgba(148, 163, 184, 0.08);
    color: rgba(226, 232, 240, 0.55);
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    transition: transform 0.12s ease, box-shadow 0.12s ease, background-color 0.2s ease, color 0.2s ease;
}
.oxy-ui .oxy-grid-cell.is-alert,
.oxy-ui .oxy-grid-cell.is-low {   /* warning or worse, any day; and the day shown's lowest, as many as share it */
    z-index: 1;
    background: rgb(var(--c, 51, 65, 85));
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22), inset 0 -1px 0 rgba(0, 0, 0, 0.12);
    color: #f8fafc;
}
.oxy-ui .oxy-grid-pen.is-gap,
.oxy-ui .oxy-grid-cell.is-gap { margin-top: 7px; }
@media (hover: hover) {
    .oxy-ui .oxy-grid-cell:hover { z-index: 2; transform: scale(1.12); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.9), 0 4px 10px rgba(0, 0, 0, 0.5); }
}
@supports (text-box: trim-both cap alphabetic) {   /* as the chips: a cell's DO and a pen's name in their boxes' middles */
    .oxy-ui .oxy-grid-cell { text-box: trim-both cap alphabetic; }
    .oxy-ui .oxy-grid-pen { padding-top: 5px; padding-bottom: 5px; text-box: trim-both cap alphabetic; }
}

.oxy-ui .oxy-grid-key {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 14px;
    margin-top: 12px;
    font-size: 10px;
    color: rgba(226, 232, 240, 0.65);
    font-variant-numeric: tabular-nums;
}
.oxy-ui .oxy-key::before {
    content: "";
    display: inline-block;
    width: 10px;
    height: 10px;
    margin-right: 5px;
    border-radius: 2px;
    vertical-align: -1px;
}
.oxy-ui .oxy-key-red::before { background: #b91c1c; }
.oxy-ui .oxy-key-amber::before { background: #8f6d15; }   /* as the cells: amber and the pale blues deepened for their white text */
.oxy-ui .oxy-key-ok::before { background: linear-gradient(90deg, #377b84, #2572cc 55%, #14587f); }

/* A pen: back, its name and its status (a pill as the side panel's farm cards' status, .oxy-chip: their rules below);
   the hour shown and its lowest to come; its dial; its stocking density. */
.oxy-ui .oxy-pen-head { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.oxy-ui .oxy-pen-back { margin-left: -6px; }
.oxy-ui .oxy-pen-name { min-width: 0; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-family: Oxanium, sans-serif; font-size: 24px; font-weight: 700; letter-spacing: 0.4px; line-height: 1.1; color: #f8fafc; }
.oxy-ui .oxy-pen-status { margin-left: auto; }
/* The hour shown, and under it the lowest to come: centred over the dial, a line each, so none wraps however long it
   is. (The DO at that hour is in the dial's middle.) */
.oxy-ui .oxy-pen-now { margin: 10px 0 0; text-align: center; font-size: 12px; color: rgba(226, 232, 240, 0.6); font-variant-numeric: tabular-nums; }
.oxy-ui .oxy-pen-now p { margin: 0; line-height: 1.35; white-space: nowrap; }
.oxy-ui .oxy-pen-now .js-now-at { font-size: 10px; font-weight: 700; letter-spacing: 0.8px; text-transform: uppercase; }
.oxy-ui .oxy-pen-now .oxy-pen-low { margin-top: 2px; font-weight: 600; }
.oxy-ui .oxy-pen-low.oxy-red { color: #f87171; }
.oxy-ui .oxy-pen-low.oxy-amber { color: #fbbf24; }
/* An empty pen: no DO, only "Not stocked". */
.oxy-ui .oxy-pen-now.is-empty { display: none; }   /* an empty pen: no DO; the density's place says "Not stocked" */

/* The dial: the pen's forecast as a ring of hours (a canvas over it all) round the 3D pen, which sits in a porthole of
   water just inside the ring (DIAL.inner of its width, in oxy_farm_view.js). */
.oxy-ui .oxy-dial { position: relative; width: 100%; aspect-ratio: 1; margin: 6px 0 8px; }
.oxy-ui .oxy-dial-pen {
    position: absolute;
    inset: 19%;
    border-radius: 50%;
    overflow: hidden;
    background: radial-gradient(circle at 50% 42%, rgba(46, 142, 255, 0.16), rgba(2, 10, 24, 0.75) 72%);
    box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.12), inset 0 -18px 30px rgba(0, 0, 0, 0.35);
}
.oxy-ui .oxy-dial-pen canvas { display: block; width: 100%; height: 100%; }
.oxy-ui .oxy-dial-ring { position: absolute; inset: 0; width: 100%; height: 100%; }
.oxy-ui .oxy-dial-ring.is-hour { cursor: pointer; }
/* The DO at the moment shown (or the hour hovered), over the 3D pen in the middle of the porthole's bottom third
   (the porthole is .oxy-dial-pen, inset 19%: its radius 31% of the dial, so that third's middle is 2/3 of the radius
   below the centre): plain text, no box, shadowed so it reads over the pen. */
.oxy-ui .oxy-dial-now {
    position: absolute;
    left: 50%;
    top: calc(50% + (50% - 19%) * 2 / 3);
    transform: translate(-50%, -50%);
    margin: 0;
    color: #f8fafc;
    font-size: 13px;
    line-height: 1.2;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 3px rgba(2, 6, 23, 0.8), 0 0 10px rgba(2, 6, 23, 0.6);
    pointer-events: none;   /* the ring under it still hears the pointer */
}
.oxy-ui .oxy-dial-now b { font-weight: 500; }
.oxy-ui .oxy-dial-none {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    color: rgba(226, 232, 240, 0.55);
    pointer-events: none;
}

/* Stocking density, in a tile under the dial, as the sum it is: density = biomass ÷ net volume. Its figures one size,
   in a row, each sign centred in the room between two (on the figures' line: each term's label, figure and species
   rows a subgrid of the tile's); the density leads, its label in the brand's blue (it is the 3D pen's haze); the
   species under the biomass, as small as the labels, on one line that takes no room in the row (so the signs stay
   even). An empty pen's tile says only "Not stocked". */
.oxy-ui .oxy-density,
.oxy-ui .oxy-density-none {
    margin: 0;
    padding: 10px 14px 11px;
    border-radius: 12px;
    background: rgba(148, 163, 184, 0.06);
    border: 1px solid rgba(148, 163, 184, 0.14);
}
.oxy-ui .oxy-density-none { text-align: center; font-size: 12px; font-weight: 600; color: rgba(226, 232, 240, 0.6); }
.oxy-ui .oxy-density {
    display: grid;
    grid-template-columns: auto minmax(14px, 1fr) auto minmax(14px, 1fr) auto;
    grid-template-rows: auto auto auto;
}
.oxy-ui .oxy-density > div { display: grid; grid-row: 1 / 4; grid-template-rows: subgrid; align-content: start; min-width: 0; }
.oxy-ui .oxy-density > div:nth-child(1) { grid-column: 1; }
.oxy-ui .oxy-density > div:nth-child(2) { grid-column: 3; }
.oxy-ui .oxy-density > div:nth-child(3) { grid-column: 5; }
.oxy-ui .oxy-density::before,
.oxy-ui .oxy-density::after {
    grid-row: 2;
    align-self: center;
    justify-self: center;
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    color: rgba(148, 163, 184, 0.7);
}
.oxy-ui .oxy-density::before { grid-column: 2; content: "="; content: "=" / ""; }   /* "/ ''": a sign, not read out */
.oxy-ui .oxy-density::after { grid-column: 4; content: "÷"; content: "÷" / ""; }
.oxy-ui .oxy-density dt { font-size: 10px; font-weight: 500; letter-spacing: 0.3px; color: rgba(203, 213, 225, 0.6); }
.oxy-ui .oxy-density-main dt { color: #93c5fd; }
.oxy-ui .oxy-density dd { margin: 2px 0 0; font-size: 15px; font-weight: 600; line-height: 1.15; color: #e2e8f0; font-variant-numeric: tabular-nums; white-space: nowrap; }
.oxy-ui .oxy-density-main dd { color: #f8fafc; }
.oxy-ui .oxy-density .oxy-density-species { width: 0; margin-top: 3px; font-size: 10px; font-weight: 500; letter-spacing: 0.3px; line-height: 1.3; color: #f8fafc; white-space: nowrap; }
.oxy-ui .oxy-density-species::first-letter { text-transform: uppercase; }


@media (prefers-reduced-motion: reduce) {
    .oxy-ui.oxy-player,
    .oxy-ui .oxy-player-day,
    .oxy-ui .oxy-player-play,
    .oxy-ui .oxy-grid-cell,
    .oxy-ui .oxy-grid-day,
    .oxy-ui .oxy-card,
    .oxy-ui .oxy-fc-toggle i { transition: none; }
}

/* Phone: the farm is fitted smaller, so the pens sit closer; keep their labels from touching. The bar spans the
   bottom, above the row of the map-layer switcher (app.css #map-layer-switcher) and Leaflet's zoom, with touch-sized
   controls either side of the time and scrubber; the days scroll sideways. */
@media (max-width: 600px) {
    .oxy-ui .leaflet-tooltip.oxy-pen-label { padding: 0 2px; font-size: 10px; line-height: 13px; }
    .oxy-ui.oxy-player {
        left: 8px;
        right: 8px;
        bottom: calc(84px + env(safe-area-inset-bottom, 0px));
        transform: none;
        width: auto;
        max-width: none;
        grid-template-rows: auto;
        grid-template-areas: "play time low close" "play scrub scrub close" "days days days days";
        column-gap: 10px;
        row-gap: 10px;
        padding: 8px 10px 12px;
    }
    .oxy-ui .oxy-player-close { width: 44px; height: 44px; margin-right: 0; }
    .oxy-ui .oxy-player-close svg { width: 16px; height: 16px; }
    .oxy-ui .oxy-player-track { height: 40px; }
    .oxy-ui .oxy-player-day { flex: 0 0 auto; min-width: 54px; min-height: 44px; scroll-snap-align: start; }
    .oxy-ui .oxy-player-days { scroll-snap-type: x proximity; scroll-padding: 0 5px; }   /* snap clear of the ring */
    /* The farm card is a sheet above the bar, folded to its header until opened (or a pen is). */
    .oxy-ui.oxy-farm-card {
        top: auto;
        left: 8px;
        right: 8px;
        bottom: var(--below, 240px);
        width: auto;
        max-height: min(56vh, calc(100vh - 80px - var(--below, 240px)));
        padding: 10px 12px 12px;
    }
    .oxy-ui .oxy-fc-head.oxy-red::before,
    .oxy-ui .oxy-fc-head.oxy-amber::before { left: -13px; }
    .oxy-ui .oxy-fc-name { font-size: 16px; }
    .oxy-ui .oxy-fc-toggle,
    .oxy-ui .oxy-pen-back { width: 44px; height: 44px; }
    .oxy-ui .oxy-fc-toggle { margin: -10px -10px -10px auto; }
    .oxy-ui .oxy-grid-cell { height: 28px; }
}
