/* The shell: status strip, tabs (top on wide screens, a thumb-reach dock on phones), stage, backdrop. */

.backdrop {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.field-canvas {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}
#app {
  position: relative;
  z-index: 1;
  height: 100%;
}
.shell {
  position: relative;
  display: grid;
  grid-template-rows: calc(var(--strip-h) + env(safe-area-inset-top, 0px)) minmax(0, 1fr);
  height: 100%;
}

/* ---------------------------------------------------------------- strip */
.strip {
  position: relative;
  z-index: 20;
  display: flex;
  align-items: stretch;
  /* Opened from the home screen the page runs under the status bar and round the corners. */
  padding: env(safe-area-inset-top, 0px) max(var(--gutter), env(safe-area-inset-right, 0px)) 0 max(var(--gutter), env(safe-area-inset-left, 0px));
  background: var(--void);
  border-bottom: var(--hair) solid var(--line-2);
}
.brand {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-right: var(--s5);
  color: var(--ink);
  text-decoration: none;
}
.brand-mark {
  color: var(--cyan);
}
.brand-name {
  font: 500 var(--t-small)/1 var(--f-display);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.brand-sub {
  color: var(--ink-3);
  font-weight: 500;
}
.strip-title {
  display: none;
  align-items: center;
  font: 500 var(--t-small)/1 var(--f-display);
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.tabs {
  display: flex;
}
.tab {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: 0 var(--s4);
  color: var(--ink-3);
  font: 500 var(--t-small)/1 var(--f-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
}
.tab .icon,
.tab-short {
  display: none;
}
/* Slanted dividers: the one place the strip shows the angle of the cut corners. */
.tab + .tab::before {
  content: "";
  position: absolute;
  left: 0;
  top: 21px;
  bottom: 21px;
  width: 1px;
  background: var(--line-2);
  transform: skewX(-24deg);
}
.tab:hover {
  color: var(--ink);
}
.tab[aria-current="page"] {
  color: var(--ink);
}
.tab[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: var(--s4);
  right: var(--s4);
  bottom: -1px;
  height: var(--bold);
  background: var(--cyan);
}
.tab:focus-visible {
  outline-offset: -4px;
}
.tab-count {
  font: 400 var(--t-micro)/1 var(--f-mono);
  letter-spacing: 0;
  color: var(--ink-3);
}
.tab-count:empty {
  display: none;
}

.strip-status {
  display: flex;
  align-items: center;
  gap: var(--s5);
  margin-left: auto;
}
.stat-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  white-space: nowrap;
}
.stat-label {
  font: 500 var(--t-micro) / 1 var(--f-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.stat-value {
  font: 400 var(--t-small) / 1 var(--f-mono);
  color: var(--ink-2);
}
.stat-chip.is-warm .stat-value {
  color: var(--gold);
}
.lockwrap {
  position: relative;
  display: flex;
  align-items: center;
}
.lockchip {
  --edge: var(--line-2);
  --c: var(--cut-s);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 40px;
  padding: 0 var(--s3);
  border: var(--hair) solid var(--edge);
  color: var(--ink-2);
  font: 500 var(--t-mini)/1 var(--f-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  clip-path: polygon(0 0, calc(100% - var(--cut-s)) 0, 100% var(--cut-s), 100% 100%, 0 100%);
}
.lockchip:hover {
  --edge: var(--line-3);
  color: var(--ink);
}
/* Unlocked is the everyday state and stays quiet. Locked is the exception, and is gold. */
.lockchip.is-locked {
  --edge: var(--gold-line);
  background: var(--gold-fill);
  color: var(--gold);
}
.lockchip.is-locked:hover {
  --edge: var(--gold);
}
.chip-time {
  min-width: 7ch;
  font: 400 var(--t-small) / 1 var(--f-mono);
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
  text-align: right;
}
.chip-time:empty {
  display: none;
}
.pop {
  position: absolute;
  top: calc(100% + var(--s2));
  right: 0;
  z-index: 40;
  width: 328px;
  padding: var(--s4) var(--s4) var(--s5);
  background: linear-gradient(to top right, transparent calc(50% - 0.75px), var(--line-3) calc(50% - 0.75px), var(--line-3) calc(50% + 0.75px), transparent calc(50% + 0.75px)) top right / var(--cut) var(--cut) no-repeat border-box, var(--near);
  border: var(--hair) solid var(--line-3);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
  transform-origin: top right;
  animation: pop-in 180ms var(--ease-out);
}
@keyframes pop-in {
  from {
    opacity: 0;
    transform: scale(0.92);
  }
}
.signout {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  min-height: 40px;
  color: var(--ink-3);
  font: 500 var(--t-mini)/1 var(--f-display);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
}
.signout:hover {
  color: var(--ink);
}

/* ---------------------------------------------------------------- stage and the way views arrive */
.stage {
  position: relative;
  min-height: 0;
  overflow: hidden;
}
.view {
  position: absolute;
  inset: 0;
  overflow: auto;
  overscroll-behavior: contain;
  padding-bottom: var(--dock-h);
  /* What the keyboard moves to is scrolled clear of the phone's dock, not under it. */
  scroll-padding-bottom: calc(var(--dock-h) + var(--s2));
}
/* A view arrives from depth: it starts smaller and further away, and its planes follow in order.
   The one before it leaves toward the viewer. Transform and opacity only. */
.view.is-arriving {
  animation: view-arrive var(--arrive) var(--ease-out) both;
}
.view.is-arriving .plane {
  animation: plane-arrive 280ms var(--ease-out) both;
  animation-delay: calc(var(--order, 0) * 40ms + 30ms);
}
/* Stacked, a plane is as tall as its content: a long text, a long list. Tipping something thousands
   of pixels tall throws its far end hundreds of pixels out of place (and makes one enormous layer),
   so here the planes arrive flat: they rise a little and fade in, in the same order. */
@media (max-width: 1040px) {
  .view.is-arriving .plane {
    animation-name: plane-arrive-flat;
  }
}
.view.is-leaving {
  animation: view-leave 150ms var(--ease-in) both;
  pointer-events: none;
}
@keyframes view-arrive {
  from {
    opacity: 0;
    transform: scale(0.95);
  }
}
@keyframes plane-arrive {
  from {
    opacity: 0;
    transform: perspective(1400px) translate3d(0, 10px, -90px) rotateX(5deg);
  }
  to {
    transform: perspective(1400px) translate3d(0, 0, 0) rotateX(0deg);
  }
}
@keyframes plane-arrive-flat {
  from {
    opacity: 0;
    transform: translate3d(0, 10px, 0);
  }
}
@keyframes view-leave {
  to {
    opacity: 0;
    transform: scale(1.04);
  }
}

/* A view that is still loading, and one that failed to: in the middle of the stage. */
.view-wait,
.view-fault {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: var(--s5) var(--gutter) calc(var(--dock-h) + var(--s5));
}
.view-wait {
  pointer-events: none;
  animation: view-arrive var(--arrive) var(--ease-out) both;
}
#app > .view-fault {
  position: fixed;
}
/* Shown by boot.js when the console's own files could not be loaded. */
.boot-failed {
  max-width: 44ch;
  margin: 20vh auto 0;
  padding: 0 var(--gutter);
  color: var(--ink-2);
  text-align: center;
}

/* ---------------------------------------------------------------- narrower */
/* Six tabs beside the status readouts. As the strip narrows, the tabs close up, then "console", the
   model's state, the words "Sign out" and the power figure give way one at a time. Each step is taken
   early enough that the strip is never wider than the page, even with the lock chip at its longest
   ("Locked 24:00:00"). */
@media (max-width: 1380px) {
  .tab {
    padding: 0 var(--s3);
  }
  .tab[aria-current="page"]::after {
    left: var(--s3);
    right: var(--s3);
  }
}
@media (max-width: 1320px) {
  .brand-sub {
    display: none;
  }
}
@media (max-width: 1260px) {
  .stat-chip.is-model {
    display: none;
  }
}
@media (max-width: 1120px) {
  .signout-label {
    display: none;
  }
  .strip-status {
    gap: var(--s3);
  }
}
@media (max-width: 1040px) {
  .stat-chip:not(.is-offline) {
    display: none;
  }
  .tab-long {
    display: none;
  }
  .tab-short {
    display: inline;
  }
}
/* The narrowest strip that still has the tabs in it: the mark alone, as on a phone, and the tabs closer. */
@media (max-width: 900px) and (min-width: 761px) {
  .brand {
    min-width: 40px;
    padding-right: var(--s2);
  }
  .brand-name {
    display: none;
  }
  .tab {
    padding: 0 var(--s2);
  }
  .tab[aria-current="page"]::after {
    left: var(--s2);
    right: var(--s2);
  }
}

/* ---------------------------------------------------------------- phone: tabs become a dock under the thumb */
@media (max-width: 760px) {
  /* The mark alone, and still a full-size target for a thumb. */
  .brand {
    min-width: 40px;
    padding-right: var(--s3);
  }
  .brand-name {
    display: none;
  }
  .strip-title {
    display: flex;
  }
  .strip-status {
    gap: var(--s1);
  }
  /* There is no room for it here; the toast says the same. */
  .stat-chip.is-offline {
    display: none;
  }
  .signout {
    width: 40px;
    justify-content: center;
  }
  .tabs {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 30;
    display: grid;
    /* Six tabs, 60 px each on the narrowest phone (360 px): the longest names just fit at this size. */
    grid-template-columns: repeat(6, minmax(0, 1fr));
    height: var(--dock-h);
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--void);
    border-top: var(--hair) solid var(--line-2);
  }
  .tab {
    flex-direction: column;
    justify-content: center;
    gap: var(--s1);
    padding: 0;
    font-size: var(--t-micro);
    letter-spacing: 0.06em;
  }
  .tab .icon {
    display: block;
  }
  .tab + .tab::before {
    display: none;
  }
  .tab[aria-current="page"] {
    color: var(--cyan);
  }
  .tab[aria-current="page"] .tab-label {
    color: var(--ink);
  }
  .tab[aria-current="page"]::after {
    top: -1px;
    bottom: auto;
    left: 26%;
    right: 26%;
  }
  .tab-count {
    position: absolute;
    top: 9px;
    left: calc(50% + 12px);
  }
  /* On the narrowest phones six names of eight letters stand shoulder to shoulder: set a little tighter, they keep a gap. */
  @media (max-width: 400px) {
    .tab {
      letter-spacing: 0.02em;
    }
  }
  .pop {
    position: fixed;
    top: calc(var(--strip-h) + env(safe-area-inset-top, 0px) + 8px);
    left: var(--gutter);
    right: var(--gutter);
    width: auto;
  }
}
