
:root{--logo:#0fa3a0;--brand:#0b7977;--orange:#e8862a;--ink:#0c1a2b;--slate:#556575;
--paper:#f5f8f9;--line:#dae2e8;--line-soft:#eef2f5;--alarm:#b3261e;--measure:70ch;
--surface:#fff;--code-bg:#0f1a15;--code-ink:#e8f0ea;--code-btn:#1d2f26;--code-btn-ink:#cfe3d6;
--code-btn-line:#2c4438;--code-btn-hover:#274034;
--note-bg:#fdf6ef;--note-line:#f0d3b0;--warn-bg:#fdf3f2;--warn-line:#f0c4c1;
/* One easing curve and two durations for the whole site. Motion that differs
   from element to element reads as several people's work; motion that agrees
   reads as one surface. The curve leaves quickly and arrives gently, which is
   what makes a panel feel light rather than mechanical. */
--ease:cubic-bezier(.22,.9,.3,1);--fast:.15s;--normal:.24s;
--shadow-1:0 1px 2px rgba(12,26,43,.05);
--shadow-2:0 20px 44px rgba(12,26,43,.14),0 3px 10px rgba(12,26,43,.06);
--scrim:rgba(12,26,43,.42);color-scheme:light}

/* Dark mode. Resolved into an actual answer by the script in the head before
   the first paint, which is why there is no prefers-color-scheme query and the
   tokens are written once. */
:root[data-theme=dark]{--brand:#3fb8b4;--ink:#e6eef4;--slate:#93a6b6;
--paper:#0a121a;--line:#22303d;--line-soft:#1a2531;--alarm:#e8756b;
--surface:#111c27;--code-bg:#060d14;--code-ink:#e6eef4;--code-btn:#16232f;
--code-btn-ink:#93a6b6;--code-btn-line:#22303d;--code-btn-hover:#1d2c3a;
--note-bg:#241c11;--note-line:#4a3a1e;--warn-bg:#2a1614;--warn-line:#4d2724;
/* Shadows do less work on a dark ground, so they go deeper rather than
   disappear, and the scrim goes darker to keep the panel legible over it. */
--shadow-1:0 1px 2px rgba(0,0,0,.4);
--shadow-2:0 20px 44px rgba(0,0,0,.55),0 3px 10px rgba(0,0,0,.35);
--scrim:rgba(2,8,14,.62);color-scheme:dark}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
html,body{margin:0;padding:0;background:var(--paper);color:var(--ink);
font:16px/1.65 Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}
::selection{background:var(--brand);color:#fff}
h1,h2,h3{font-family:Poppins,ui-sans-serif,system-ui,sans-serif;font-weight:600;
margin:2.25rem 0 .6rem;letter-spacing:-.015em;line-height:1.22;text-wrap:balance}
h1{font-size:1.9rem;margin-top:0}h2{font-size:1.3rem}h3{font-size:1.05rem}
p,ul,ol{max-width:var(--measure)}p{margin:0 0 1rem;text-wrap:pretty}
a{color:var(--brand);text-underline-offset:.18em;text-decoration-thickness:.07em;
transition:color var(--fast) var(--ease)}
a:hover{text-decoration:underline}
code{font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.87em;
background:var(--surface);border:1px solid var(--line);border-radius:4px;padding:.08em .32em}
pre{background:var(--code-bg);color:var(--code-ink);padding:1rem 1.15rem;border-radius:10px;overflow-x:auto;
font-family:"JetBrains Mono",ui-monospace,monospace;font-size:.84rem;line-height:1.6;
box-shadow:var(--shadow-1)}
pre code{background:none;border:0;padding:0;color:inherit;font-size:inherit}
.shell{display:grid;grid-template-columns:250px 1fr;min-height:100vh;max-width:1180px;margin:0 auto}
.rail{border-right:1px solid var(--line);background:var(--surface);padding:1.5rem 1.25rem;
position:sticky;top:0;height:100vh;overflow-y:auto}
.wordmark{display:flex;align-items:center;color:var(--ink);text-decoration:none}
.wordmark .logo{display:block;width:auto}
.wordmark:hover{text-decoration:none}
.rail nav{margin-top:1.5rem;display:flex;flex-direction:column;gap:1px}
.rail nav a{padding:.4rem .6rem;border-radius:6px;color:var(--ink);text-decoration:none;font-size:.9rem;
transition:background var(--fast) var(--ease),color var(--fast) var(--ease)}
.rail nav a:hover{background:var(--paper);text-decoration:none}
/* The page you are on is marked by an edge rather than by weight alone. Weight
   alone is a difference you have to look for. */
.rail nav a[aria-current=page]{background:var(--paper);font-weight:600;
box-shadow:inset 2px 0 0 var(--brand)}
main{padding:2.5rem 3rem;min-width:0}
footer{margin-top:4rem;padding-top:1.5rem;border-top:1px solid var(--line);
color:var(--slate);font-size:.82rem}
table{border-collapse:collapse;width:100%;font-size:.9rem;margin:1rem 0;display:block;overflow-x:auto}
th{text-align:left;padding:.5rem .7rem;border-bottom:1px solid var(--line);color:var(--slate)}
td{padding:.5rem .7rem;border-bottom:1px solid var(--line-soft);vertical-align:top}
tr{transition:background var(--fast) var(--ease)}
tbody tr:hover,table tr:hover{background:var(--line-soft)}
.note{border:1px solid var(--note-line);background:var(--note-bg);padding:.9rem 1.1rem;border-radius:8px;
margin:1.25rem 0;max-width:var(--measure)}
.warn{border:1px solid var(--warn-line);background:var(--warn-bg);padding:.9rem 1.1rem;border-radius:8px;
margin:1.25rem 0;max-width:var(--measure)}
/* A section behind its own head, for the parts of a page that have to be here
and are not what the reader came for. Meta's Business Cloud API is the one that
gets this treatment everywhere - the console folds its tiers, the marketing
site folds its packages and its explanation, and so does this. */
details.fold{border:1px solid var(--line);border-radius:8px;margin:1.25rem 0;
max-width:var(--measure);background:var(--surface);overflow:hidden}
details.fold>summary{cursor:pointer;padding:.75rem 1.1rem;font-weight:600;
list-style:none;display:flex;align-items:center;gap:.6rem}
details.fold>summary::-webkit-details-marker{display:none}
details.fold>summary::before{content:"";flex:none;width:7px;height:7px;
border-right:2px solid var(--slate);border-bottom:2px solid var(--slate);
transform:rotate(-45deg);transition:transform var(--fast) var(--ease)}
details.fold[open]>summary::before{transform:rotate(45deg)}
details.fold>summary:hover{color:var(--brand)}
details.fold .fold-body{padding:0 1.1rem .35rem;border-top:1px solid var(--line-soft)}
.hero{display:flex;flex-direction:column;justify-content:center;min-height:78vh;max-width:760px}
.hero h1{font-size:2.4rem}.hero p{font-size:1.05rem;color:var(--slate)}
.copy{position:relative}
.copy button{position:absolute;top:.6rem;right:.6rem;background:var(--code-btn);color:var(--code-btn-ink);
border:1px solid var(--code-btn-line);border-radius:5px;padding:.25rem .6rem;font-size:.75rem;cursor:pointer;
font-family:inherit}
.copy button{transition:background var(--fast) var(--ease),transform var(--fast) var(--ease)}
.copy button:hover{background:var(--code-btn-hover)}
.copy button:active{transform:translateY(1px)}
.pill{display:inline-block;border:1px solid var(--line);background:var(--surface);border-radius:999px;
padding:.1rem .55rem;font-size:.75rem;color:var(--slate);
transition:border-color var(--fast) var(--ease),color var(--fast) var(--ease)}
button.pill:hover{border-color:var(--brand);color:var(--brand)}
.err-list{columns:2;column-gap:2rem;max-width:none}
.err-list a{display:block;padding:.15rem 0;font-size:.88rem;font-family:"JetBrains Mono",monospace}
/* Always in the layout, hidden by opacity and visibility rather than by
   display, because display cannot be transitioned. The delay on visibility is
   what lets the fade finish before the element is taken away; without it the
   panel vanishes on the first frame and the transition is never seen. */
#palette{position:fixed;inset:0;background:var(--scrim);display:flex;
align-items:flex-start;justify-content:center;padding-top:12vh;z-index:50;
opacity:0;visibility:hidden;
transition:opacity var(--normal) var(--ease),visibility 0s linear var(--normal)}
#palette.open{opacity:1;visibility:visible;transition-delay:0s,0s}
#palette .box{background:var(--surface);border-radius:12px;width:min(560px,92vw);
border:1px solid var(--line);overflow:hidden;box-shadow:var(--shadow-2);
transform:translateY(-8px) scale(.985);
transition:transform var(--normal) var(--ease)}
#palette.open .box{transform:none}
#palette input{width:100%;border:0;border-bottom:1px solid var(--line);padding:.9rem 1.1rem;
font:inherit;outline:none;background:var(--surface);color:var(--ink)}
#palette ul{list-style:none;margin:0;padding:.4rem;max-height:52vh;overflow-y:auto}
#palette li a{display:block;padding:.45rem .7rem;border-radius:6px;color:var(--ink);
text-decoration:none;font-size:.9rem}
#palette li a{transition:background var(--fast) var(--ease)}
#palette li a:hover,#palette li a.sel{background:var(--paper)}
:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
/* Search and the theme, on one line: the two things in this rail that are not
   navigation. Quiet until pointed at, so neither competes with the page. */
.rail-tools{display:flex;align-items:center;gap:.5rem;margin-top:1rem}
.rail-tools .pill{margin:0}
.theme-toggle{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;
padding:0;margin-left:auto;border:1px solid transparent;border-radius:6px;background:transparent;
color:var(--slate);cursor:pointer;transition:color .15s ease,background .15s ease,border-color .15s ease}
.theme-toggle:hover{color:var(--brand);background:var(--surface);border-color:var(--line)}
.theme-toggle svg{display:none}
.theme-toggle[data-state=light] .i-sun,.theme-toggle[data-state=dark] .i-moon,
.theme-toggle[data-state=system] .i-system,.theme-toggle:not([data-state]) .i-system{display:block}
/* The menu button. Absent on a desktop, where the rail is a sidebar and the
   links are simply there. */
.rail-top{display:flex;align-items:center;gap:.75rem}
.rail-toggle{display:none;align-items:center;gap:.4rem;margin-left:auto;
padding:.42rem .65rem;border:1px solid var(--line);border-radius:8px;
background:var(--surface);color:var(--ink);font:inherit;font-size:.8rem;cursor:pointer;
transition:border-color var(--fast) var(--ease),color var(--fast) var(--ease),
transform var(--fast) var(--ease)}
.rail-toggle:hover{border-color:var(--brand);color:var(--brand)}
.rail-toggle:active{transform:translateY(1px)}
/* The dialog carries its own header. On a desktop the same element is the
   sidebar, which needs neither a second wordmark nor a way to be closed. */
.rail-dialog-top{display:none}

/* Phones.
 *
 * The rail is a sidebar on a desktop and a bar across the top on a phone. It
 * used to wrap ten links across three rows, and with a hero asking for 78vh
 * underneath them the first line of every page began below the fold: what you
 * saw on opening the docs was a menu and an empty screen.
 *
 * So it is a menu now, and it opens over the page rather than pushing it down.
 * Pushing means every word you were reading moves while you are reading it,
 * and moves back when you dismiss the thing you opened. A layer that arrives
 * on top leaves the page exactly where you left it. */
@media (max-width:860px){.shell{grid-template-columns:1fr}
.rail{position:sticky;top:0;z-index:30;height:auto;border-right:0;
border-bottom:1px solid var(--line);background:var(--surface);padding:.85rem 1.25rem;
transition:box-shadow var(--normal) var(--ease);
/* The desktop rail scrolls its own links, so it carries overflow-y:auto. Left
   in place here that clips the panel, which hangs below the bar and is exactly
   the thing that must not be cut off. */
overflow:visible}
/* Once the page is running underneath, the bar has to sit above it, and a
   shadow is how a surface says so. At the top of the page there is nothing to
   sit above, so there is no shadow. */
:root[data-scrolled=true] .rail{box-shadow:var(--shadow-1)}
.rail .wordmark svg{height:24px;width:auto}
.rail-toggle{display:inline-flex}
.kbd-hint{display:none}

/* The menu is the screen. Not a panel hanging off a bar with the page showing
   underneath it, which asks somebody to read a menu and the thing behind it at
   once, but a single surface from the top of the display to the bottom.
   Whatever it is covering stops being relevant the moment it opens.

   It covers the bar rather than dodging it.
   Dodging was the mistake: the panel is a child of the rail, the rail carries a
   z-index and so is a stacking context, and inside one of those a child cannot
   be put behind its own parent however small its z-index. The bar was still
   there, painted over by the panel, and the menu had no visible way to close.
   
   Covering it needs no z-index argument and no measurement of anything. The
   dialog's own header sits in normal flow with the same padding as the bar, so
   the close button lands where the menu button was and nothing appears to
   move. */
.rail[data-collapsible] .rail-panel{
position:fixed;inset:0;z-index:60;background:var(--surface);
padding:.85rem 1.25rem 2rem;
overflow-y:auto;overscroll-behavior:contain;
transform:translateY(-6px);opacity:0;visibility:hidden;
transition:transform var(--normal) var(--ease),opacity var(--fast) var(--ease),
visibility 0s linear var(--normal)}
.rail[data-collapsible] .rail-dialog-top{display:flex;align-items:center;gap:.75rem;
margin-bottom:1.35rem}
.rail[data-collapsible] .rail-dialog-top .wordmark svg{height:24px;width:auto}
.rail[data-collapsible] .rail-dialog-top .rail-toggle{display:inline-flex}
.rail[data-collapsible][data-open=true] .rail-panel{
transform:none;opacity:1;visibility:visible;transition-delay:0s,0s,0s}

/* The page does not scroll behind an open menu. Scrolling something you cannot
   see is the clearest way to tell somebody the layer they opened is not real. */
:root[data-menu=open]{overflow:hidden}

.rail-tools{margin-top:0;margin-bottom:1.1rem}
/* A whole screen for ten links is room to make them comfortable rather than
   room to leave empty. A 32px row is a row somebody taps twice. */
.rail nav{margin-top:0;gap:1px}
.rail nav a{min-height:48px;display:flex;align-items:center;font-size:1.02rem;
padding:.55rem .7rem;border-radius:8px}

.hero{min-height:auto;justify-content:flex-start}
.hero h1{font-size:1.9rem}
main{padding:1.5rem 1.25rem}.err-list{columns:1}}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}
*{transition:none!important;animation:none!important}}
