# The GigCharts vocabulary
# https://www.gigcharts.app/ns/gigchart
#
# The terms behind the .gigchart interchange format. The published JSON-LD context
# (https://www.gigcharts.app/context/gigchart.jsonld) declares this namespace as its @vocab, so every
# key in a .gigchart file that the context does not map explicitly still expands into this
# namespace. This document defines the core terms; the full key-by-key specification of the
# format lives at https://www.gigcharts.app/format.
#
# A human-readable rendering of this file is at https://www.gigcharts.app/ns/gigchart.

@prefix gc:      <https://www.gigcharts.app/ns/gigchart#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:     <http://www.w3.org/2002/07/owl#> .
@prefix xsd:     <http://www.w3.org/2001/XMLSchema#> .
@prefix schema:  <https://schema.org/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix vann:    <http://purl.org/vocab/vann/> .

# ---------------------------------------------------------------------------
# The ontology
# ---------------------------------------------------------------------------

<https://www.gigcharts.app/ns/gigchart#> a owl:Ontology ;
  dcterms:title "The GigCharts vocabulary"@en ;
  dcterms:description "Terms for the .gigchart chord-chart interchange format: the chart document, the annotations that make it performable, and the identifiers that tie a chart to the song it sets."@en ;
  dcterms:publisher <https://www.gigcharts.app/> ;
  dcterms:license <https://creativecommons.org/licenses/by/4.0/> ;
  vann:preferredNamespaceUri "https://www.gigcharts.app/ns/gigchart#" ;
  vann:preferredNamespacePrefix "gc" ;
  rdfs:seeAlso <https://www.gigcharts.app/format> , <https://www.gigcharts.app/context/gigchart.jsonld> ;
  owl:versionInfo "Published with .gigchart format version 12."@en .

# Terms are added, not repurposed: a term that appears here keeps its meaning for good. A key that
# a later format version stops writing keeps its definition rather than being deleted, so an
# archived file stays readable.

gc:serializedAs a rdf:Property ;
  rdfs:label "serialized as"@en ;
  rdfs:domain rdf:Property ;
  rdfs:range xsd:string ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The JSON key this term is written as in a .gigchart file, when it differs from the term's own local name."@en .

# ---------------------------------------------------------------------------
# Classes
# ---------------------------------------------------------------------------

gc:Chart a rdfs:Class ;
  rdfs:label "Chart"@en ;
  rdfs:subClassOf schema:CreativeWork ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A GigCharts chart document: one performable arrangement of one song, together with the typesetting and performance annotations that make it a gig sheet. This is the type of the .gigchart envelope — the node that carries the file's own identifier. A Chart is about a musical composition but is not itself the composition: the composition hangs off it as gc:song."@en .

# Annotation kinds. The context aliases the file's `kind` key to @type, so an annotation node
# expands with the class named by its own kind token. Local names are lowercase because they are
# the file's tokens verbatim.

gc:section a rdfs:Class ;
  rdfs:label "section"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A labeled spine beside a stanza or a run of stanzas — Verse, Chorus, Bridge."@en .

gc:cue a rdfs:Class ;
  rdfs:label "cue"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A small labeled chip carrying a performance note. The most-used annotation kind."@en .

gc:repeat a rdfs:Class ;
  rdfs:label "repeat"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A repeat bar with a times-N count beside a stanza."@en .

gc:markers a rdfs:Class ;
  rdfs:label "markers"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Bar or beat markers along a stanza."@en .

gc:roadmap a rdfs:Class ;
  rdfs:label "roadmap"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A stacked arrangement map — one bar per section, in performance order."@en .

gc:recall a rdfs:Class ;
  rdfs:label "recall"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A recall mark: a pointer back to a stanza already printed, so a repeated chorus need not be set again. Its refStanza / refSid names the stanza it points at. Spelled chorus inside the app; recall is the file spelling and the normative one."@en .

gc:capo a rdfs:Class ;
  rdfs:label "capo"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The capo indicator in the header chrome."@en .

gc:voice a rdfs:Class ;
  rdfs:label "voice"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A voice assignment — which singer or part takes a stanza, a line, or a word range. Carries the color the voice is drawn in."@en .

gc:pagebreak a rdfs:Class ;
  rdfs:label "pagebreak"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A forced page break before the targeted stanza."@en .

gc:info a rdfs:Class ;
  rdfs:label "info"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A placed copy of the song info box."@en .

gc:chordbox a rdfs:Class ;
  rdfs:label "chordbox"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A placed box of chords, typed rather than derived from the body."@en .

gc:linkedchordbox a rdfs:Class ;
  rdfs:label "linkedchordbox"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A chord box that is a live reference to another stanza's chords rather than typed text; it follows that stanza when the chords change."@en .

gc:qr a rdfs:Class ;
  rdfs:label "qr"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A placed QR code carrying its own link, unrelated to the song's video property. It may print as the square or as a text link instead; its linkMode says which."@en .

gc:textbox a rdfs:Class ;
  rdfs:label "textbox"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A free text box placed on the page."@en .

# Target kinds. The same `kind` alias applies inside an annotation's target.

gc:stanza a rdfs:Class ;
  rdfs:label "stanza"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets a whole stanza, by 0-based index and/or by its sticky stanza id."@en .

gc:span a rdfs:Class ;
  rdfs:label "span"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets an inclusive run of stanzas — one spine or bar covering several."@en .

gc:line a rdfs:Class ;
  rdfs:label "line"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets one rendered row inside a stanza."@en .

gc:range a rdfs:Class ;
  rdfs:label "range"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets a word range: a column range on one lyric row."@en .

gc:gap a rdfs:Class ;
  rdfs:label "gap"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets the space after a given stanza. The reading application converts this to a spacer on load."@en .

gc:spacer a rdfs:Class ;
  rdfs:label "spacer"@en ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Targets an explicit spacer block, by its id."@en .

# ---------------------------------------------------------------------------
# Properties
# ---------------------------------------------------------------------------

gc:format a rdf:Property ;
  rdfs:label "format"@en ;
  rdfs:domain gc:Chart ;
  rdfs:range xsd:string ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The format discriminator. Always the literal string gigchart."@en .

gc:formatVersion a rdf:Property ;
  rdfs:label "format version"@en ;
  rdfs:domain gc:Chart ;
  rdfs:range xsd:integer ;
  gc:serializedAs "version" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The .gigchart format version the file is written in — not the song's own revision, which is schema:version. Serialized as the key `version`."@en .

gc:generator a rdf:Property ;
  rdfs:label "generator"@en ;
  rdfs:domain gc:Chart ;
  rdfs:range xsd:string ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Which software build wrote the file, e.g. gigcharts.app v0.9.0 (a1b2c3d). The tiebreaker when two files share a format version but came from different builds."@en .

gc:song a rdf:Property ;
  rdfs:label "song"@en ;
  rdfs:domain gc:Chart ;
  rdfs:range schema:MusicComposition ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Links a chart document to the musical composition it sets. The composition node carries the song's identity metadata and the chart's own content — body, annotations, settings."@en .

gc:properties a rdf:Property ;
  rdfs:label "properties"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Groups the song's identity metadata — title, credits, key, tempo, rights. A structural grouping in the JSON serialization, not a semantic relation; the terms inside it are the schema.org ones."@en .

gc:localId a rdf:Property ;
  rdfs:label "local id"@en ;
  rdfs:range xsd:string ;
  gc:serializedAs "id" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A handle that is unique inside one chart and meaningless outside it — an annotation id, a spacer id, a voice id. Deliberately NOT the node's @id: these are relative names, not IRIs, and reading them as identifiers would drop every node carrying one from the RDF. Only the chart document's own id, a urn:uuid, is a real identifier. Serialized as the key `id`."@en .

gc:body a rdf:Property ;
  rdfs:label "body"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdf:List ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The chart itself: the ordered lines of chords and lyrics, one entry per line, an empty string separating stanzas. An RDF list, because line order is the chart — an unordered set of lines is not a song."@en .

gc:structure a rdf:Property ;
  rdfs:label "structure"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdf:List ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The stanza-id ledger: one sticky id per stanza of the body, in body order. These are what an annotation's stanza anchors point at, so a target survives edits to the body above it. An RDF list — the ledger is positional."@en .

gc:spacers a rdf:Property ;
  rdfs:label "spacers"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdf:List ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "Explicit blocks of vertical space between stanzas, each able to host a gap-scoped annotation. An RDF list: where two spacers share a boundary, stack order is array order."@en .

gc:duration a rdf:Property ;
  rdfs:label "duration"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range xsd:string ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The song's playing time as a display string, conventionally mm:ss (for example 3:45). Deliberately NOT schema:duration: that property's range is an ISO-8601 duration (PT3M45S), and asserting a display string into it would be a range violation. A future format version may add an ISO-8601 spelling alongside this one."@en .

gc:mbWork a rdf:Property ;
  rdfs:label "MusicBrainz work"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbTitleUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the work this chart sets. Captured from metadata autocomplete and carried with the file so the song's identity survives outside GigCharts."@en .

gc:mbArtist a rdf:Property ;
  rdfs:label "MusicBrainz artist"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbArtistUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the performing artist."@en .

gc:mbRelease a rdf:Property ;
  rdfs:label "MusicBrainz release"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbAlbumUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the release the song appears on."@en .

gc:mbComposer a rdf:Property ;
  rdfs:label "MusicBrainz composer"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbMusicUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the composer."@en .

gc:mbLyricist a rdf:Property ;
  rdfs:label "MusicBrainz lyricist"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbLyricsUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the lyricist."@en .

gc:mbArranger a rdf:Property ;
  rdfs:label "MusicBrainz arranger"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbArrangerUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the arranger. Added in v12: on traditional and folk material the arrangement is frequently the only authored layer there is to credit, so the arranger is as worth identifying as the composer."@en .

gc:mbInstrument a rdf:Property ;
  rdfs:label "MusicBrainz instrument"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbInstrumentUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the instrument the chart is written for. Added in v12 alongside the Instrument field's controlled vocabulary: MusicBrainz holds instruments as entities with their own identifiers, so \"guitar\", \"Guitar\" and \"gtr\" stop being three different instruments."@en .

gc:mbGenre a rdf:Property ;
  rdfs:label "MusicBrainz genre"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "mbGenreUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable MusicBrainz URI for the chart's genre. Added in v12 with the bundled genre vocabulary: MusicBrainz curates 2181 terms with identifiers but publishes no way to search them, so GigCharts ships the list and stores the id."@en .

gc:regionRef a rdf:Property ;
  rdfs:label "region identifier"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "regionUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable identifier for the region the song comes from — in practice a Wikidata item, e.g. Q832218 for Kalotaszeg. Deliberately not named for one authority: a place may as reasonably be identified by GeoNames or the Getty TGN, and the URI states which one. Added in v12."@en .

gc:occasionRef a rdf:Property ;
  rdfs:label "occasion identifier"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "holidayUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable identifier for the occasion or feast day the song belongs to — in practice a Wikidata item. Added in v12; same reasoning as regionRef."@en .

gc:languageRef a rdf:Property ;
  rdfs:label "language identifier"@en ;
  rdfs:subPropertyOf rdfs:seeAlso ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range rdfs:Resource ;
  gc:serializedAs "languageUri" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "A resolvable identifier for the language of the lyrics — a Wikidata item, e.g. Q9067 for Hungarian. Added in v12. The alternatives considered were Lexvo (lexvo.org/id/iso639-3/hun), which is purpose-built for languages, and the bare ISO 639-3 code, which is the real identifier but has no official URI form; Wikidata won because it is the authority the region and occasion fields already use."@en .

gc:videoFetched a rdf:Property ;
  rdfs:label "video looked up on"@en ;
  rdfs:domain schema:MusicComposition ;
  rdfs:range xsd:date ;
  gc:serializedAs "videoFetched" ;
  rdfs:isDefinedBy <https://www.gigcharts.app/ns/gigchart#> ;
  rdfs:comment "The date the cached facts about the video link (title, channel) were fetched — the \"accessed on\" of a citation. Added in v12. It qualifies gc:videoTitle and gc:videoAuthor, which are a cache of somebody else's page rather than assertions of our own."@en .
